Skip to content

Commit b3dfc9f

Browse files
committed
Fix crash on empty parameters to generic data type
When no parameters are passed to generic data types we cannot properly infer the usage of the generic block. This brings in a canonicalized check for `rustc --explain E0107` Fixes #379
1 parent 498758a commit b3dfc9f

File tree

6 files changed

+71
-54
lines changed

6 files changed

+71
-54
lines changed

gcc/rust/hir/tree/rust-hir-path.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,11 @@ struct GenericArgs
165165
GenericArgs &operator= (GenericArgs &&other) = default;
166166

167167
// Creates an empty GenericArgs (no arguments)
168-
static GenericArgs create_empty ()
168+
static GenericArgs create_empty (Location locus = Location ())
169169
{
170170
return GenericArgs (std::vector<Lifetime> (),
171171
std::vector<std::unique_ptr<Type> > (),
172-
std::vector<GenericArgsBinding> ());
172+
std::vector<GenericArgsBinding> (), locus);
173173
}
174174

175175
bool is_empty () const

gcc/rust/typecheck/rust-hir-type-check-toplevel.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,7 @@ class TypeCheckTopLevel : public TypeCheckBase
214214
auto self
215215
= TypeCheckType::Resolve (impl_block.get_type ().get (), &substitutions);
216216
if (self == nullptr || self->get_kind () == TyTy::TypeKind::ERROR)
217-
{
218-
rust_error_at (impl_block.get_locus (), "failed to resolve impl type");
219-
return;
220-
}
217+
return;
221218

222219
for (auto &impl_item : impl_block.get_impl_items ())
223220
TypeCheckTopLevelImplItem::Resolve (impl_item.get (), self,

gcc/rust/typecheck/rust-hir-type-check-type.h

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class TypeCheckResolveGenericArguments : public TypeCheckBase
7272
public:
7373
static HIR::GenericArgs resolve (HIR::TypePathSegment *segment)
7474
{
75-
TypeCheckResolveGenericArguments resolver;
75+
TypeCheckResolveGenericArguments resolver (segment->get_locus ());
7676
segment->accept_vis (resolver);
7777
return resolver.args;
7878
};
@@ -83,8 +83,8 @@ class TypeCheckResolveGenericArguments : public TypeCheckBase
8383
}
8484

8585
private:
86-
TypeCheckResolveGenericArguments ()
87-
: TypeCheckBase (), args (HIR::GenericArgs::create_empty ())
86+
TypeCheckResolveGenericArguments (Location locus)
87+
: TypeCheckBase (), args (HIR::GenericArgs::create_empty (locus))
8888
{}
8989

9090
HIR::GenericArgs args;
@@ -165,57 +165,57 @@ class TypeCheckType : public TypeCheckBase
165165
return;
166166
}
167167

168-
// reverse lookup the hir node from ast node id
169168
HirId hir_lookup;
170-
if (context->lookup_type_by_node_id (ref, &hir_lookup))
169+
if (!context->lookup_type_by_node_id (ref, &hir_lookup))
171170
{
172-
// we got an HIR node
173-
if (context->lookup_type (hir_lookup, &translated))
174-
{
175-
translated = translated->clone ();
176-
auto ref = path.get_mappings ().get_hirid ();
177-
translated->set_ref (ref);
178-
179-
HIR::TypePathSegment *final_seg = path.get_final_segment ();
180-
HIR::GenericArgs args
181-
= TypeCheckResolveGenericArguments::resolve (final_seg);
182-
183-
bool path_declared_generic_arguments = !args.is_empty ();
184-
if (path_declared_generic_arguments)
185-
{
186-
if (translated->has_subsititions_defined ())
187-
{
188-
translated
189-
= SubstMapper::Resolve (translated, path.get_locus (),
190-
&args);
191-
if (translated->get_kind () != TyTy::TypeKind::ERROR
192-
&& mappings != nullptr)
193-
{
194-
check_for_unconstrained (args.get_type_args ());
195-
}
196-
}
197-
else
198-
{
199-
rust_error_at (
200-
path.get_locus (),
201-
"TypePath %s declares generic argument's but "
202-
"the type %s does not have any",
203-
path.as_string ().c_str (),
204-
translated->as_string ().c_str ());
205-
}
206-
}
207-
else if (translated->has_subsititions_defined ())
208-
{
209-
translated
210-
= SubstMapper::InferSubst (translated, path.get_locus ());
211-
}
171+
rust_error_at (path.get_locus (), "failed to lookup HIR node");
172+
return;
173+
}
174+
175+
TyTy::BaseType *lookup = nullptr;
176+
if (!context->lookup_type (hir_lookup, &lookup))
177+
{
178+
rust_error_at (path.get_locus (), "failed to lookup HIR TyTy");
179+
return;
180+
}
181+
182+
TyTy::BaseType *path_type = lookup->clone ();
183+
path_type->set_ref (path.get_mappings ().get_hirid ());
184+
185+
HIR::TypePathSegment *final_seg = path.get_final_segment ();
186+
HIR::GenericArgs args
187+
= TypeCheckResolveGenericArguments::resolve (final_seg);
188+
189+
bool is_big_self = final_seg->is_ident_only ()
190+
&& (final_seg->as_string ().compare ("Self") == 0);
212191

192+
if (path_type->needs_generic_substitutions ())
193+
{
194+
if (is_big_self)
195+
{
196+
translated = path_type;
213197
return;
214198
}
215-
}
216199

217-
rust_error_at (path.get_locus (), "failed to type-resolve TypePath: %s",
218-
path.as_string ().c_str ());
200+
translated = SubstMapper::Resolve (path_type, path.get_locus (), &args);
201+
if (translated->get_kind () != TyTy::TypeKind::ERROR
202+
&& mappings != nullptr)
203+
{
204+
check_for_unconstrained (args.get_type_args ());
205+
}
206+
}
207+
else if (!args.is_empty ())
208+
{
209+
rust_error_at (path.get_locus (),
210+
"TypePath %s declares generic argument's but "
211+
"the type %s does not have any",
212+
path.as_string ().c_str (),
213+
translated->as_string ().c_str ());
214+
}
215+
else
216+
{
217+
translated = path_type;
218+
}
219219
}
220220

221221
void visit (HIR::ArrayType &type) override

gcc/rust/typecheck/rust-substitution-mapper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class SubstMapper : public TyTy::TyVisitor
5757
{
5858
TyTy::SubstitutionArgumentMappings mappings
5959
= type.get_mappings_from_generic_args (*generics);
60+
if (mappings.is_error ())
61+
return;
62+
6063
concrete = type.handle_substitions (mappings);
6164
}
6265

@@ -77,6 +80,9 @@ class SubstMapper : public TyTy::TyVisitor
7780
{
7881
TyTy::SubstitutionArgumentMappings mappings
7982
= type.get_mappings_from_generic_args (*generics);
83+
if (mappings.is_error ())
84+
return;
85+
8086
concrete = type.handle_substitions (mappings);
8187
}
8288

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
struct Foo<A>(A);
2+
3+
fn main() {
4+
let a: Foo = Foo::<i32>(123);
5+
// { dg-error "Invalid number of generic arguments to generic type" "" { target { *-*-* } } .-1 }
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
struct Foo<A>(A);
2+
3+
impl Foo {
4+
// { dg-error "Invalid number of generic arguments to generic type" "" { target { *-*-* } } .-1 }
5+
fn test() -> i32 {
6+
123
7+
}
8+
}

0 commit comments

Comments
 (0)