Skip to content

WIP: Fix unexpected E0110 when using GATs #51589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 67 additions & 19 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::GenericParamDefKind;
use rustc::ty::wf::object_region_bounds;
use rustc_target::spec::abi;
use std::slice;
use require_c_abi_if_variadic;
use util::common::ErrorReported;
use util::nodemap::{FxHashSet, FxHashMap};
Expand Down Expand Up @@ -217,21 +216,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let ty_provided = parameters.types.len();
let lt_provided = parameters.lifetimes.len();

let mut lt_accepted = 0;
let mut ty_params = ParamRange { required: 0, accepted: 0 };
for param in &decl_generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {
lt_accepted += 1;
}
GenericParamDefKind::Type { has_default, .. } => {
ty_params.accepted += 1;
if !has_default {
ty_params.required += 1;
}
}
};
}
let (mut ty_params, lt_accepted) = accepted_argument_count_of(decl_generics);

if self_ty.is_some() {
ty_params.required -= 1;
ty_params.accepted -= 1;
Expand Down Expand Up @@ -866,8 +852,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {

debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);

self.prohibit_type_params(slice::from_ref(item_segment));

// Find the type of the associated item, and the trait where the associated
// item is declared.
let bound = match (&ty.sty, ty_path_def) {
Expand Down Expand Up @@ -919,6 +903,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
})
.expect("missing associated type");

// Make sure the supplied parameters match the declared parameter of
// the associated type.
let (ty_provided, lt_provided) = match &item_segment.parameters {
Some(params) => (params.types.len(), params.lifetimes.len()),
None => (0, 0),
};

let (ty_params, lt_accepted)
= accepted_argument_count_of(tcx.generics_of(item.def_id));

if lt_accepted != lt_provided {
report_lifetime_number_error(tcx, span, lt_provided, lt_accepted);
}
check_type_argument_count(tcx, span, ty_provided, ty_params);


let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I see what's missing here - projected_ty_from_poly_trait_ref should not exist. create_substs_for_ast_path should be used, and it now needs to handle multiple segments containing parameters, which is unprecedenced.

let ty = self.normalize_ty(span, ty);

Expand All @@ -943,7 +943,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let tcx = self.tcx();
let trait_def_id = tcx.parent_def_id(item_def_id).unwrap();

self.prohibit_type_params(slice::from_ref(item_segment));
// Make sure the supplied parameters match the declared parameter of
// the associated type.
let (ty_provided, lt_provided) = match &item_segment.parameters {
Some(params) => (params.types.len(), params.lifetimes.len()),
None => (0, 0),
};

let (ty_params, lt_accepted)
= accepted_argument_count_of(tcx.generics_of(item_def_id));

if lt_accepted != lt_provided {
report_lifetime_number_error(tcx, span, lt_provided, lt_accepted);
}
check_type_argument_count(tcx, span, ty_provided, ty_params);


let self_ty = if let Some(ty) = opt_self_ty {
ty
Expand Down Expand Up @@ -1054,7 +1068,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
tcx.mk_self_type()
}
Def::AssociatedTy(def_id) => {
// TODO: why is this here? Maybe it should be removed now?
self.prohibit_type_params(&path.segments[..path.segments.len()-2]);

self.qpath_to_ty(span,
opt_self_ty,
def_id,
Expand Down Expand Up @@ -1350,6 +1366,38 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
(auto_traits, trait_bounds)
}

/// Given the generic parameters of a definition, this function returns
/// information about how many lifetime and type parameters can be applied when
/// referencing the item. That is:
///
/// - the number of accepted lifetime parameters
/// - the number of required and the number of accepted type parameters
///
/// For example, for `struct Foo<T = u32>` this function returns:
/// `(0, ParamRange { required: 0, accepted: 1})`. For `struct Bar<'a, T>` this
/// function returns: `(1, ParamRange { required: 1, accepted: 1})`.
fn accepted_argument_count_of<'tcx>(
generics: &'tcx ty::Generics
) -> (ParamRange, usize) {
let mut lt_accepted = 0;
let mut ty_params = ParamRange { required: 0, accepted: 0 };
for param in &generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {
lt_accepted += 1;
}
GenericParamDefKind::Type { has_default, .. } => {
ty_params.accepted += 1;
if !has_default {
ty_params.required += 1;
}
}
};
}

(ty_params, lt_accepted)
}

fn check_type_argument_count(tcx: TyCtxt,
span: Span,
supplied: usize,
Expand Down