Skip to content
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

Do not eagerly reject inference vars when trying to resolve method calls. #126316

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1567,7 +1567,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let rcvr_t = self.check_expr(rcvr);
// no need to check for bot/err -- callee does that
let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
let rcvr_t = self.try_structurally_resolve_type(rcvr.span, rcvr_t);

let method = match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args)
{
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ fn method_autoderef_steps<'tcx>(

let final_ty = autoderef.final_ty(true);
let opt_bad_ty = match final_ty.kind() {
ty::Infer(ty::TyVar(_)) if !reached_raw_pointer => None,
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
reached_raw_pointer,
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2543,7 +2543,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
.map_err(|e| {
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
})?;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! This test used to ICE #121613
//! Using a generic parameter where there are none expected
//! caused an ICE, hiding the important later errors.

#![feature(more_qualified_paths)]

fn main() {
let _ = <Foo as A>::Assoc { br: 2 };

let <E>::V(..) = E::V(|a, b| a.cmp(b));
//~^ ERROR: multiple applicable items in scope
}

struct StructStruct {
br: i8,
}

struct Foo;

trait A {
type Assoc;
}

impl A for Foo {
type Assoc = StructStruct;
}

enum E {
V(u8),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0034]: multiple applicable items in scope
--> $DIR/param_mismatch_on_associatedtype_constructor.rs:10:36
|
LL | let <E>::V(..) = E::V(|a, b| a.cmp(b));
| ^^^ multiple `cmp` found
|
note: candidate #1 is defined in the trait `Iterator`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
note: candidate #2 is defined in the trait `Ord`
--> $SRC_DIR/core/src/cmp.rs:LL:COL
help: disambiguate the method for candidate #1
|
LL | let <E>::V(..) = E::V(|a, b| Iterator::cmp(a, b));
| ~~~~~~~~~~~~~~~~~~~
help: disambiguate the method for candidate #2
|
LL | let <E>::V(..) = E::V(|a, b| Ord::cmp(&a, b));
| ~~~~~~~~~~~~~~~

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0034`.
19 changes: 19 additions & 0 deletions tests/ui/auto-traits/opaque_type_candidate_selection.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0119]: conflicting implementations of trait `Trait<_>`
--> $DIR/opaque_type_candidate_selection.rs:28:1
|
LL | impl<T> Trait<T> for T {
| ---------------------- first implementation here
...
LL | impl<T> Trait<T> for defining_scope::Alias<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

error[E0282]: type annotations needed
--> $DIR/opaque_type_candidate_selection.rs:11:23
|
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0119, E0282.
For more information about an error, try `rustc --explain E0119`.
12 changes: 12 additions & 0 deletions tests/ui/auto-traits/opaque_type_candidate_selection.old.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0119]: conflicting implementations of trait `Trait<_>`
--> $DIR/opaque_type_candidate_selection.rs:28:1
|
LL | impl<T> Trait<T> for T {
| ---------------------- first implementation here
...
LL | impl<T> Trait<T> for defining_scope::Alias<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
33 changes: 33 additions & 0 deletions tests/ui/auto-traits/opaque_type_candidate_selection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//@revisions: old next
//@[next] compile-flags: -Znext-solver

//! used to ICE: #119272

#![feature(type_alias_impl_trait)]
mod defining_scope {
use super::*;
pub type Alias<T> = impl Sized;

pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
//[next]~^ ERROR: type annotations needed
x
}
}

struct Container<T: Trait<U>, U> {
x: <T as Trait<U>>::Assoc,
}

trait Trait<T> {
type Assoc;
}

impl<T> Trait<T> for T {
type Assoc = Box<u32>;
}
impl<T> Trait<T> for defining_scope::Alias<T> {
//~^ ERROR: conflicting implementations
type Assoc = usize;
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl<F, R, A1, A2> Wrap<F> for Value<Rc<dyn Fn(A1, A2) -> R>> {
}
}

impl<F> Deref for Value<Rc<F>> {
impl<F: ?Sized> Deref for Value<Rc<F>> {
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
type Target = F;

fn deref(&self) -> &Self::Target {
Expand All @@ -29,12 +29,12 @@ impl<F> Deref for Value<Rc<F>> {

fn main() {
let var_fn = Value::wrap();
//~^ ERROR type annotations needed for `Value<Rc<_>>`

// The combination of `Value: Wrap` obligation plus the autoderef steps
// (caused by the `Deref` impl above) actually means that the self type
// of the method fn below is constrained to be `Value<Rc<dyn Fn(?0, ?1) -> ?2>>`.
// However, that's only known to us on the error path -- we still need
// to emit an ambiguity error, though.
let _ = var_fn.clone();
//~^ ERROR type annotations needed
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
error[E0282]: type annotations needed for `Value<Rc<_>>`
--> $DIR/deref-ambiguity-becomes-nonambiguous.rs:31:9
error[E0283]: type annotations needed
--> $DIR/deref-ambiguity-becomes-nonambiguous.rs:38:9
|
LL | let var_fn = Value::wrap();
| ^^^^^^
...
LL | let _ = var_fn.clone();
| ----- type must be known at this point
| ^ ------ ----- required by a bound introduced by this call
| |
| type must be known at this point
|
help: consider giving `var_fn` an explicit type, where the placeholders `_` are specified
= note: cannot satisfy `_: Clone`
help: consider giving this pattern a type
|
LL | let var_fn: Value<Rc<_>> = Value::wrap();
| ++++++++++++++
LL | let _: /* Type */ = var_fn.clone();
| ++++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0283`.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | needs_foo(|x| {
| ^
...
LL | x.to_string();
| - type must be known at this point
| ------------- type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/call_method_ambiguous.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | let mut iter = foo(n - 1, m);
| ^^^^^^^^
LL |
LL | assert_eq!(iter.get(), 1);
| ---- type must be known at this point
| ---------- type must be known at this point
|
help: consider giving `iter` an explicit type
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | let x = my_foo();
| ^
LL |
LL | x.my_debug();
| - type must be known at this point
| ------------ type must be known at this point
|
help: consider giving `x` an explicit type
|
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0282]: type annotations needed for `&_`
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:14:13
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:15:13
|
LL | let x = &my_foo();
| ^
LL |
LL | x.my_debug();
| -------- type must be known at this point
| ------------ type must be known at this point
|
help: consider giving `x` an explicit type, where the placeholders `_` are specified
|
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@[current] check-pass

trait MyDebug {
fn my_debug(&self);
Expand All @@ -14,7 +15,6 @@ fn my_foo() -> impl std::fmt::Debug {
let x = &my_foo();
//[next]~^ ERROR: type annotations needed
x.my_debug();
//[current]~^ ERROR: no method named `my_debug`
}
()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | let x = my_foo();
| ^
LL |
LL | x.my_debug();
| - type must be known at this point
| ------------ type must be known at this point
|
help: consider giving `x` an explicit type
|
Expand All @@ -19,7 +19,7 @@ LL | let x = &my_bar();
| ^
LL |
LL | x.my_debug();
| -------- type must be known at this point
| ------------ type must be known at this point
|
help: consider giving `x` an explicit type, where the placeholders `_` are specified
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/equality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo {
0
} else {
n + sum_to(n - 1)
//~^ ERROR cannot add `impl Foo` to `u32`
//~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
}
}

Expand Down
15 changes: 4 additions & 11 deletions tests/ui/impl-trait/equality.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,13 @@ help: change the type of the numeric literal from `u32` to `i32`
LL | 0_i32
| ~~~

error[E0277]: cannot add `impl Foo` to `u32`
error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
--> $DIR/equality.rs:24:11
|
LL | n + sum_to(n - 1)
| ^ no implementation for `u32 + impl Foo`
|
= help: the trait `Add<impl Foo>` is not implemented for `u32`
= help: the following other types implement trait `Add<Rhs>`:
`&u32` implements `Add<u32>`
`&u32` implements `Add`
`u32` implements `Add<&u32>`
`u32` implements `Add`
| ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`

error: aborting due to 2 previous errors; 1 warning emitted

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0284, E0308.
For more information about an error, try `rustc --explain E0284`.
30 changes: 7 additions & 23 deletions tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
error[E0282]: type annotations needed
--> $DIR/hidden-type-is-opaque-2.rs:10:17
error[E0599]: no method named `reify_as` found for type `_` in the current scope
--> $DIR/hidden-type-is-opaque-2.rs:11:14
|
LL | Thunk::new(|mut cont| {
| ^^^^^^^^
LL |
LL | cont.reify_as();
| ---- type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
LL | Thunk::new(|mut cont: /* Type */| {
| ++++++++++++
| ^^^^^^^^ method not found in `_`

error[E0282]: type annotations needed
--> $DIR/hidden-type-is-opaque-2.rs:20:17
error[E0599]: no method named `reify_as` found for type `_` in the current scope
--> $DIR/hidden-type-is-opaque-2.rs:21:14
|
LL | Thunk::new(|mut cont| {
| ^^^^^^^^
LL |
LL | cont.reify_as();
| ---- type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
LL | Thunk::new(|mut cont: /* Type */| {
| ++++++++++++
| ^^^^^^^^ method not found in `_`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0599`.
Loading