Skip to content
Open
Show file tree
Hide file tree
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
5 changes: 4 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&[path_str],
item_segment.ident,
assoc_tag,
Applicability::MachineApplicable,
)
}

Expand Down Expand Up @@ -698,6 +699,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&traits,
ident,
assoc_tag,
Applicability::MaybeIncorrect,
)
}
}
Expand All @@ -709,6 +711,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
traits: &[String],
ident: Ident,
assoc_tag: ty::AssocTag,
applicability: Applicability,
) -> ErrorGuaranteed {
let kind_str = assoc_tag_str(assoc_tag);
let mut err =
Expand Down Expand Up @@ -807,7 +810,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
sugg_sp,
"use fully-qualified syntax",
suggestions,
Applicability::MachineApplicable,
applicability,
SuggestionStyle::ShowAlways,
);
}
Expand Down
49 changes: 23 additions & 26 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,19 @@ use rustc_errors::{
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::DynCompatibilityViolation;
use rustc_lint_defs::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::consts::ConstExt;
use rustc_middle::ty::{
self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput,
Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast,
const_lit_matches_ty, fold_regions,
Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, Unnormalized, Upcast, const_lit_matches_ty,
};
use rustc_session::diagnostics::feature_err;
use rustc_span::def_id::{LocalModId, ModId};
use rustc_span::{DUMMY_SP, Ident, Span, bug, kw, span_bug, sym};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_span::{Ident, Span, bug, kw, span_bug, sym};
use rustc_trait_selection::traits::{self, FulfillmentError};
use tracing::{debug, instrument};

Expand Down Expand Up @@ -1860,16 +1858,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
) -> Vec<String> {
let tcx = self.tcx();

// In contexts that have no inference context, just make a new one.
// We do need a local variable to store it, though.
let infcx_;
let infcx = if let Some(infcx) = self.infcx() {
infcx
} else {
assert!(!qself_ty.has_infer());
infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
&infcx_
};
// Deep rejection cannot rule out unrelated impls for unresolved aliases.
// Avoid offering misleading suggestions for those types.
if qself_ty.has_aliases() {
return Vec::new();
}

// FIXME: Support non-lifetime binders without suggesting unrelated traits.
if qself_ty.has_non_region_bound_vars() {
return Vec::new();
}

tcx.all_traits_including_private()
.filter(|trait_def_id| {
Expand All @@ -1887,19 +1885,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let header = tcx.impl_trait_header(impl_def_id);
let trait_ref = header.trait_ref.instantiate(tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id)).skip_norm_wip();

let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
// FIXME: Don't bother dealing with non-lifetime binders here...
if value.has_escaping_bound_vars() {
if header.polarity == ty::ImplPolarity::Negative {
return false;
}
infcx
.can_eq(
ty::ParamEnv::empty(),
trait_ref.self_ty(),
value,
) && header.polarity != ty::ImplPolarity::Negative

let impl_ty = header
.trait_ref
.instantiate_identity()
.skip_norm_wip()
.self_ty();

ty::DeepRejectCtxt::relate_rigid_infer(tcx)
.types_may_unify(qself_ty, impl_ty)
})
})
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Regression test for issue #163320: ambiguous associated-type paths
// involving const generics must not ICE during item lowering or type checking.

//@ compile-flags: -Znext-solver=globally
//@ check-fail

#![feature(generic_const_parameter_types)]

fn where_clause<const N: usize>()
where
<[(); N] as IntoIterator>::Item::Item:,
//~^ ERROR ambiguous associated type
{}

fn nested_where<const N: usize>()
where
Option<<[(); N] as IntoIterator>::Item::Item>: Sized,
//~^ ERROR ambiguous associated type
{}

fn parameter<const N: usize>(
_: <[(); N] as IntoIterator>::Item::Item,
//~^ ERROR ambiguous associated type
) {}

type Alias<const N: usize> =
<[(); N] as IntoIterator>::Item::Item;
//~^ ERROR ambiguous associated type

struct Field<const N: usize> {
field: <[(); N] as IntoIterator>::Item::Item,
//~^ ERROR ambiguous associated type
}

struct Parent<const N: usize>;

impl<const N: usize> Parent<N> {
fn inherited()
where
<[(); N] as IntoIterator>::Item::Item:,
//~^ ERROR ambiguous associated type
{}
}

struct ConstParameter<
const N: usize,
const M: <[(); N] as IntoIterator>::Item::Item,
//~^ ERROR ambiguous associated type
>;

struct TypeParameterDefault<
const N: usize,
T = <[(); N] as IntoIterator>::Item::Item,
//~^ ERROR ambiguous associated type
>(std::marker::PhantomData<T>);

fn in_body<const N: usize>() {
let _: <[(); N] as IntoIterator>::Item::Item;
//~^ ERROR ambiguous associated type
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:11:5
|
LL | <[(); N] as IntoIterator>::Item::Item:,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - <[(); N] as IntoIterator>::Item::Item:,
LL + <<[(); N] as IntoIterator>::Item as Example>::Item:,
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:17:12
|
LL | Option<<[(); N] as IntoIterator>::Item::Item>: Sized,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - Option<<[(); N] as IntoIterator>::Item::Item>: Sized,
LL + Option<<<[(); N] as IntoIterator>::Item as Example>::Item>: Sized,
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:22:8
|
LL | _: <[(); N] as IntoIterator>::Item::Item,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - _: <[(); N] as IntoIterator>::Item::Item,
LL + _: <<[(); N] as IntoIterator>::Item as Example>::Item,
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:27:5
|
LL | <[(); N] as IntoIterator>::Item::Item;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - <[(); N] as IntoIterator>::Item::Item;
LL + <<[(); N] as IntoIterator>::Item as Example>::Item;
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:31:12
|
LL | field: <[(); N] as IntoIterator>::Item::Item,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - field: <[(); N] as IntoIterator>::Item::Item,
LL + field: <<[(); N] as IntoIterator>::Item as Example>::Item,
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:47:14
|
LL | const M: <[(); N] as IntoIterator>::Item::Item,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - const M: <[(); N] as IntoIterator>::Item::Item,
LL + const M: <<[(); N] as IntoIterator>::Item as Example>::Item,
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:53:9
|
LL | T = <[(); N] as IntoIterator>::Item::Item,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - T = <[(); N] as IntoIterator>::Item::Item,
LL + T = <<[(); N] as IntoIterator>::Item as Example>::Item,
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:40:9
|
LL | <[(); N] as IntoIterator>::Item::Item:,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - <[(); N] as IntoIterator>::Item::Item:,
LL + <<[(); N] as IntoIterator>::Item as Example>::Item:,
|

error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-issue-163320.rs:58:12
|
LL | let _: <[(); N] as IntoIterator>::Item::Item;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path
|
LL - let _: <[(); N] as IntoIterator>::Item::Item;
LL + let _: <<[(); N] as IntoIterator>::Item as Example>::Item;
|

error: aborting due to 9 previous errors

For more information about this error, try `rustc --explain E0223`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Regression test for the original ICE in issue #163320.
//@ compile-flags: -Znext-solver=globally --crate-type=lib
//@ check-fail

trait HasStorage {
type Storage;
}

struct Bits;

trait TryFromBits {
type Bits;
}

trait ReadEndian: TryFromBits {}

struct Zeros<const N: u32>;

impl<const N: u32> TryFromBits for Zeros<N> {
type Bits = Bits;
}

impl<const N: u32> ReadEndian for Zeros<N>
where
<Self::Bits as HasStorage>::Storage::Bits: Sized,
//~^ ERROR ambiguous associated type
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0223]: ambiguous associated type
--> $DIR/assoc-ty-const-generics-original-repro-issue-163320.rs:25:5
|
LL | <Self::Bits as HasStorage>::Storage::Bits: Sized,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `Bits` implemented for `<<Zeros<N> as TryFromBits>::Bits as HasStorage>::Storage`, you could use the fully-qualified path
|
LL - <Self::Bits as HasStorage>::Storage::Bits: Sized,
LL + <<<Zeros<N> as TryFromBits>::Bits as HasStorage>::Storage as Example>::Bits: Sized,
|

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0223`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Suggestions should not need trait solving during either item lowering or
// body type checking. Deep rejection may also admit incompatible impls.

//@ compile-flags: -Znext-solver=globally
//@ check-fail

trait Identity {
type Out;
}

impl Identity for () {
type Out = (u8, u8);
}

trait Different {
type Out;
}

impl Different for () {
type Out = (u8, u16);
}

trait HasItem {
type Item;
}

impl<T> HasItem for (T, T) {
type Item = ();
}

type Positive = <<() as Identity>::Out>::Item;
//~^ ERROR ambiguous associated type

type Negative = <<() as Different>::Out>::Item;
//~^ ERROR ambiguous associated type

fn body_positive() {
let _: <<() as Identity>::Out>::Item;
//~^ ERROR ambiguous associated type
}

fn body_negative() {
let _: <<() as Different>::Out>::Item;
//~^ ERROR ambiguous associated type
}

// Repeated impl parameters can result in false-positive suggestions.
type RepeatedParam = <(u8, u16)>::Item;
//~^ ERROR ambiguous associated type

fn main() {}
Loading
Loading