Skip to content

Commit

Permalink
Fix w/ comments
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianKnodt committed Feb 1, 2022
1 parent c654e4d commit 78fb74a
Show file tree
Hide file tree
Showing 40 changed files with 281 additions and 199 deletions.
6 changes: 6 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2165,6 +2165,12 @@ impl TypeBinding<'_> {
_ => panic!("expected equality type binding for parenthesized generic args"),
}
}
pub fn opt_const(&self) -> Option<&'_ AnonConst> {
match self.kind {
TypeBindingKind::Equality { term: Term::Const(ref c) } => Some(c),
_ => None,
}
}
}

#[derive(Debug)]
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,21 @@ impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> {

impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
fn to_trace(
_: TyCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) }
match (a, b) {
(ty::Term::Ty(a), ty::Term::Ty(b)) => {
ToTrace::to_trace(tcx, cause, a_is_expected, a, b)
}
(ty::Term::Const(a), ty::Term::Const(b)) => {
ToTrace::to_trace(tcx, cause, a_is_expected, a, b)
}
(_, _) => todo!(),
}
}
}

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2127,7 +2127,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::Types(exp_found) => self.expected_found_str_ty(exp_found),
infer::Regions(exp_found) => self.expected_found_str(exp_found),
infer::Consts(exp_found) => self.expected_found_str(exp_found),
infer::Terms(exp_found) => self.expected_found_str(exp_found),
infer::TraitRefs(exp_found) => {
let pretty_exp_found = ty::error::ExpectedFound {
expected: exp_found.expected.print_only_trait_path(),
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,6 @@ pub enum ValuePairs<'tcx> {
Types(ExpectedFound<Ty<'tcx>>),
Regions(ExpectedFound<ty::Region<'tcx>>),
Consts(ExpectedFound<&'tcx ty::Const<'tcx>>),
Terms(ExpectedFound<ty::Term<'tcx>>),
TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
}
Expand Down
25 changes: 20 additions & 5 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1356,11 +1356,26 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
normalized_ty,
data.term,
) {
values = Some(infer::ValuePairs::Terms(ExpectedFound::new(
is_normalized_ty_expected,
normalized_ty,
data.term,
)));
values = Some(match (normalized_ty, data.term) {
(ty::Term::Ty(normalized_ty), ty::Term::Ty(ty)) => {
infer::ValuePairs::Types(ExpectedFound::new(
is_normalized_ty_expected,
normalized_ty,
ty,
))
}
(ty::Term::Const(normalized_ct), ty::Term::Const(ct)) => {
infer::ValuePairs::Consts(ExpectedFound::new(
is_normalized_ty_expected,
normalized_ct,
ct,
))
}
(_, _) => span_bug!(
obligation.cause.span,
"found const or type where other expected"
),
});
err_buf = error;
err = &err_buf;
}
Expand Down
81 changes: 27 additions & 54 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,61 +199,30 @@ fn project_and_unify_type<'cx, 'tcx>(
let mut obligations = vec![];

let infcx = selcx.infcx();
match obligation.predicate.term {
ty::Term::Ty(obligation_pred_ty) => {
let normalized_ty = match opt_normalize_projection_type(
selcx,
obligation.param_env,
obligation.predicate.projection_ty,
obligation.cause.clone(),
obligation.recursion_depth,
&mut obligations,
) {
Ok(Some(n)) => n.ty().unwrap(),
Ok(None) => return Ok(Ok(None)),
Err(InProgress) => return Ok(Err(InProgress)),
};
debug!(?normalized_ty, ?obligations, "project_and_unify_type result");
match infcx
.at(&obligation.cause, obligation.param_env)
.eq(normalized_ty, obligation_pred_ty)
{
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
Ok(Ok(Some(obligations)))
}
Err(err) => {
debug!("project_and_unify_type: equating types encountered error {:?}", err);
Err(MismatchedProjectionTypes { err })
}
}
let normalized = match opt_normalize_projection_type(
selcx,
obligation.param_env,
obligation.predicate.projection_ty,
obligation.cause.clone(),
obligation.recursion_depth,
&mut obligations,
) {
Ok(Some(n)) => n,
Ok(None) => return Ok(Ok(None)),
Err(InProgress) => return Ok(Err(InProgress)),
};
debug!(?normalized, ?obligations, "project_and_unify_type result");
match infcx
.at(&obligation.cause, obligation.param_env)
.eq(normalized, obligation.predicate.term)
{
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
Ok(Ok(Some(obligations)))
}
ty::Term::Const(obligation_pred_const) => {
let normalized_const = match opt_normalize_projection_type(
selcx,
obligation.param_env,
obligation.predicate.projection_ty,
obligation.cause.clone(),
obligation.recursion_depth,
&mut obligations,
) {
Ok(Some(n)) => n.ct().unwrap(),
Ok(None) => return Ok(Ok(None)),
Err(InProgress) => return Ok(Err(InProgress)),
};
match infcx
.at(&obligation.cause, obligation.param_env)
.eq(normalized_const, obligation_pred_const)
{
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
Ok(Ok(Some(obligations)))
}
Err(err) => {
debug!("project_and_unify_type: equating consts encountered error {:?}", err);
Err(MismatchedProjectionTypes { err })
}
}
Err(err) => {
debug!("project_and_unify_type: equating types encountered error {:?}", err);
Err(MismatchedProjectionTypes { err })
}
}
}
Expand Down Expand Up @@ -934,6 +903,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
// created (and hence the new ones will quickly be
// discarded as duplicated). But when doing trait
// evaluation this is not the case, and dropping the trait
// evaluations can causes ICEs (e.g., #43132).
debug!(?ty, "found normalized ty");
obligations.extend(ty.obligations);
return Ok(Some(ty.value));
}
Expand Down Expand Up @@ -1127,6 +1098,8 @@ fn project<'cx, 'tcx>(
Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate)))
}
ProjectionCandidateSet::None => Ok(Projected::NoProgress(
// FIXME(associated_const_generics): this may need to change in the future?
// need to investigate whether or not this is fine.
selcx
.tcx()
.mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs)
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1244,17 +1244,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// the "projection predicate" for:
//
// `<T as Iterator>::Item = u32`
let def_kind = tcx.def_kind(projection_ty.skip_binder().item_def_id);
let assoc_item_def_id = projection_ty.skip_binder().item_def_id;
let def_kind = tcx.def_kind(assoc_item_def_id);
match (def_kind, term) {
(hir::def::DefKind::AssocTy, ty::Term::Ty(_))
| (hir::def::DefKind::AssocConst, ty::Term::Const(_)) => (),
(_, _) => {
let got = if let ty::Term::Ty(_) = term { "type" } else { "const" };
let expected = def_kind.descr(assoc_item_def_id);
tcx.sess
.struct_span_err(
binding.span,
"type/const mismatch in equality bind of associated field",
&format!("mismatch in bind of {expected}, got {got}"),
)
.span_note(
tcx.def_span(assoc_item_def_id),
&format!("{expected} defined here does not match {got}"),
)
.span_label(binding.span, "type/const Mismatch")
.emit();
}
}
Expand Down
64 changes: 20 additions & 44 deletions compiler/rustc_typeck/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,40 +161,26 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// We've encountered an `AnonConst` in some path, so we need to
// figure out which generic parameter it corresponds to and return
// the relevant type.
let filtered = path
.segments
.iter()
.filter_map(|seg| seg.args.map(|args| (args.args, seg)))
.find_map(|(args, seg)| {
args.iter()
.filter(|arg| arg.is_ty_or_const())
.position(|arg| arg.id() == hir_id)
.map(|index| (index, seg))
});
// FIXME(associated_const_equality): recursively search through the bindings instead
// of just top level.
let filtered = path.segments.iter().find_map(|seg| {
seg.args?
.args
.iter()
.filter(|arg| arg.is_ty_or_const())
.position(|arg| arg.id() == hir_id)
.map(|index| (index, seg))
});

// FIXME(associated_const_generics): can we blend this with iteration above?
let (arg_index, segment) = match filtered {
None => {
let binding_filtered = path
.segments
.iter()
.filter_map(|seg| seg.args.map(|args| (args.bindings, seg)))
.find_map(|(bindings, seg)| {
bindings
.iter()
.filter_map(|binding| {
if let hir::TypeBindingKind::Equality { term: Term::Const(c) } =
binding.kind
{
Some(c)
} else {
None
}
})
.position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg))
});
let binding_filtered = path.segments.iter().find_map(|seg| {
seg.args?
.bindings
.iter()
.filter_map(TypeBinding::opt_const)
.position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg))
});
match binding_filtered {
Some(inner) => inner,
None => {
Expand Down Expand Up @@ -518,20 +504,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
path
.segments
.iter()
.filter_map(|seg| seg.args.map(|args| (args.bindings, seg)))
.find_map(|(bindings, seg)| {
bindings
.find_map(|seg| {
seg.args?.bindings
.iter()
.filter_map(|binding| {
if let hir::TypeBindingKind::Equality { term: Term::Const(c) } =
binding.kind
{
Some((binding, c))
} else {
None
}
})
.find_map(|(binding, ct)| if ct.hir_id == hir_id {
.find_map(|binding| if binding.opt_const()?.hir_id == hir_id {
Some((binding, seg))
} else {
None
Expand Down
26 changes: 26 additions & 0 deletions src/test/ui/associated-consts/assoc-const-eq-missing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#![feature(associated_const_equality)]
#![allow(unused)]

pub trait Foo {
const N: usize;
}

pub struct Bar;

impl Foo for Bar {
const N: usize = 3;
}


fn foo1<F: Foo<Z=3>>() {}
//~^ ERROR associated type
fn foo2<F: Foo<Z=usize>>() {}
//~^ ERROR associated type
fn foo3<F: Foo<Z=5>>() {}
//~^ ERROR associated type

fn main() {
foo1::<Bar>();
foo2::<Bar>();
foo3::<Bar>();
}
21 changes: 21 additions & 0 deletions src/test/ui/associated-consts/assoc-const-eq-missing.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0220]: associated type `Z` not found for `Foo`
--> $DIR/assoc-const-eq-missing.rs:15:16
|
LL | fn foo1<F: Foo<Z=3>>() {}
| ^ associated type `Z` not found

error[E0220]: associated type `Z` not found for `Foo`
--> $DIR/assoc-const-eq-missing.rs:17:16
|
LL | fn foo2<F: Foo<Z=usize>>() {}
| ^ associated type `Z` not found

error[E0220]: associated type `Z` not found for `Foo`
--> $DIR/assoc-const-eq-missing.rs:19:16
|
LL | fn foo3<F: Foo<Z=5>>() {}
| ^ associated type `Z` not found

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0220`.
4 changes: 2 additions & 2 deletions src/test/ui/associated-consts/assoc-const-ty-mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ impl FooTy for Bar {


fn foo<F: Foo<N=usize>>() {}
//~^ ERROR type/const mismatch
//~^ ERROR mismatch in
fn foo2<F: FooTy<T=3usize>>() {}
//~^ ERROR type/const mismatch
//~^ ERROR mismatch in

fn main() {
foo::<Bar>();
Expand Down
20 changes: 16 additions & 4 deletions src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
error: type/const mismatch in equality bind of associated field
error: mismatch in bind of associated constant, got type
--> $DIR/assoc-const-ty-mismatch.rs:23:15
|
LL | fn foo<F: Foo<N=usize>>() {}
| ^^^^^^^ type/const Mismatch
| ^^^^^^^
|
note: associated constant defined here does not match type
--> $DIR/assoc-const-ty-mismatch.rs:5:3
|
LL | const N: usize;
| ^^^^^^^^^^^^^^^

error: type/const mismatch in equality bind of associated field
error: mismatch in bind of associated type, got const
--> $DIR/assoc-const-ty-mismatch.rs:25:18
|
LL | fn foo2<F: FooTy<T=3usize>>() {}
| ^^^^^^^^ type/const Mismatch
| ^^^^^^^^
|
note: associated type defined here does not match const
--> $DIR/assoc-const-ty-mismatch.rs:9:3
|
LL | type T;
| ^^^^^^^

error: aborting due to 2 previous errors

Loading

0 comments on commit 78fb74a

Please sign in to comment.