Skip to content

Commit

Permalink
Auto merge of rust-lang#97980 - Dylan-DPC:rollup-l8exe4b, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - rust-lang#96868 (Stabilize explicit_generic_args_with_impl_trait)
 - rust-lang#97703 (some additional `need_type_info.rs` cleanup)
 - rust-lang#97812 (Suggest to swap a struct and a trait in trait impls)
 - rust-lang#97958 (ExitStatus docs fixups)
 - rust-lang#97967 (Mention `infer::Trace` methods on `infer::At` methods' docs)
 - rust-lang#97972 (Update #[doc(html_playground_url)] documentation to mention what the request will be)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 11, 2022
2 parents c845946 + 1f68d5f commit 7092d42
Show file tree
Hide file tree
Showing 51 changed files with 495 additions and 368 deletions.
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0632.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#### Note: this error code is no longer emitted by the compiler.

An explicit generic argument was provided when calling a function that
uses `impl Trait` in argument position.

Erroneous code example:

```compile_fail,E0632
```ignore (no longer an error)
fn foo<T: Copy>(a: T, b: impl Clone) {}
foo::<i32>(0i32, "abc".to_string());
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_error_messages/locales/en-US/typeck.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,6 @@ typeck-expected-return-type = expected `{$expected}` because of return type
typeck-unconstrained-opaque-type = unconstrained opaque type
.note = `{$name}` must be used in combination with a concrete type within the same module
typeck-explicit-generic-args-with-impl-trait =
cannot provide explicit generic arguments when `impl Trait` is used in argument position
.label = explicit generic argument not allowed
.note = see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
.help = add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
typeck-missing-type-params =
the type {$parameterCount ->
[one] parameter
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ declare_features! (
(accepted, dyn_trait, "1.27.0", Some(44662), None),
/// Allows integer match exhaustiveness checking (RFC 2591).
(accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None),
/// Allows explicit generic arguments specification with `impl Trait` present.
(accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701), None),
/// Allows arbitrary expressions in key-value attributes at parse time.
(accepted, extended_key_value_attributes, "1.54.0", Some(78835), None),
/// Allows resolving absolute paths as paths from other crates.
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,6 @@ declare_features! (
(active, exclusive_range_pattern, "1.11.0", Some(37854), None),
/// Allows exhaustive pattern matching on types that contain uninhabited types.
(active, exhaustive_patterns, "1.13.0", Some(51085), None),
/// Allows explicit generic arguments specification with `impl Trait` present.
(active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None),
/// Allows defining `extern type`s.
(active, extern_types, "1.23.0", Some(43467), None),
/// Allows the use of `#[ffi_const]` on foreign functions.
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ impl<'a, 'tcx> At<'a, 'tcx> {
}

/// Makes `a <: b`, where `a` may or may not be expected.
///
/// See [`At::trace_exp`] and [`Trace::sub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn sub_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()>
where
T: ToTrace<'tcx>,
Expand All @@ -122,6 +125,9 @@ impl<'a, 'tcx> At<'a, 'tcx> {
/// call like `foo(x)`, where `foo: fn(i32)`, you might have
/// `sup(i32, x)`, since the "expected" type is the type that
/// appears in the signature.
///
/// See [`At::trace`] and [`Trace::sub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn sup<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
where
T: ToTrace<'tcx>,
Expand All @@ -130,6 +136,9 @@ impl<'a, 'tcx> At<'a, 'tcx> {
}

/// Makes `expected <: actual`.
///
/// See [`At::trace`] and [`Trace::sub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn sub<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
where
T: ToTrace<'tcx>,
Expand All @@ -138,6 +147,9 @@ impl<'a, 'tcx> At<'a, 'tcx> {
}

/// Makes `expected <: actual`.
///
/// See [`At::trace_exp`] and [`Trace::eq`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn eq_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()>
where
T: ToTrace<'tcx>,
Expand All @@ -146,6 +158,9 @@ impl<'a, 'tcx> At<'a, 'tcx> {
}

/// Makes `expected <: actual`.
///
/// See [`At::trace`] and [`Trace::eq`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn eq<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
where
T: ToTrace<'tcx>,
Expand Down Expand Up @@ -176,6 +191,9 @@ impl<'a, 'tcx> At<'a, 'tcx> {
/// this can result in an error (e.g., if asked to compute LUB of
/// u32 and i32), it is meaningful to call one of them the
/// "expected type".
///
/// See [`At::trace`] and [`Trace::lub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn lub<T>(self, expected: T, actual: T) -> InferResult<'tcx, T>
where
T: ToTrace<'tcx>,
Expand All @@ -186,6 +204,9 @@ impl<'a, 'tcx> At<'a, 'tcx> {
/// Computes the greatest-lower-bound, or mutual subtype, of two
/// values. As with `lub` order doesn't matter, except for error
/// cases.
///
/// See [`At::trace`] and [`Trace::glb`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn glb<T>(self, expected: T, actual: T) -> InferResult<'tcx, T>
where
T: ToTrace<'tcx>,
Expand Down
56 changes: 10 additions & 46 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,8 @@ use rustc_hir::{Item, ItemKind, Node};
use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self,
error::TypeError,
subst::{GenericArgKind, Subst, SubstsRef},
Binder, EarlyBinder, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
TypeSuperFoldable,
};
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
Expand Down Expand Up @@ -926,10 +924,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
mut t1_out: &mut DiagnosticStyledString,
mut t2_out: &mut DiagnosticStyledString,
path: String,
sub: ty::subst::SubstsRef<'tcx>,
sub: &'tcx [ty::GenericArg<'tcx>],
other_path: String,
other_ty: Ty<'tcx>,
) -> Option<()> {
// FIXME/HACK: Go back to `SubstsRef` to use its inherent methods,
// ideally that shouldn't be necessary.
let sub = self.tcx.intern_substs(sub);
for (i, ta) in sub.types().enumerate() {
if ta == other_ty {
self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
Expand Down Expand Up @@ -960,45 +961,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

/// For generic types with parameters with defaults, remove the parameters corresponding to
/// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
fn strip_generic_default_params(
&self,
def_id: DefId,
substs: ty::subst::SubstsRef<'tcx>,
) -> SubstsRef<'tcx> {
let generics = self.tcx.generics_of(def_id);
let mut num_supplied_defaults = 0;

let default_params = generics.params.iter().rev().filter_map(|param| match param.kind {
ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id),
ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id),
_ => None,
});
for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) {
match actual.unpack() {
GenericArgKind::Const(c) => {
if EarlyBinder(self.tcx.const_param_default(def_id)).subst(self.tcx, substs)
!= c
{
break;
}
}
GenericArgKind::Type(ty) => {
if self.tcx.bound_type_of(def_id).subst(self.tcx, substs) != ty {
break;
}
}
_ => break,
}
num_supplied_defaults += 1;
}
let len = generics.params.len();
let mut generics = generics.clone();
generics.params.truncate(len - num_supplied_defaults);
substs.truncate_to(self.tcx, &generics)
}

/// Given two `fn` signatures highlight only sub-parts that are different.
fn cmp_fn_sig(
&self,
Expand Down Expand Up @@ -1156,8 +1118,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
let did1 = def1.did();
let did2 = def2.did();
let sub_no_defaults_1 = self.strip_generic_default_params(did1, sub1);
let sub_no_defaults_2 = self.strip_generic_default_params(did2, sub2);
let sub_no_defaults_1 =
self.tcx.generics_of(did1).own_substs_no_defaults(self.tcx, sub1);
let sub_no_defaults_2 =
self.tcx.generics_of(did2).own_substs_no_defaults(self.tcx, sub2);
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
let path1 = self.tcx.def_path_str(did1);
let path2 = self.tcx.def_path_str(did2);
Expand Down
48 changes: 21 additions & 27 deletions compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::infer::type_variable::TypeVariableOriginKind;
use crate::infer::InferCtxt;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{CtorOf, DefKind, Namespace};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
Expand All @@ -11,7 +12,7 @@ use rustc_middle::infer::unify_key::ConstVariableOriginKind;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, InferConst};
use rustc_middle::ty::{self, DefIdTree, InferConst};
use rustc_middle::ty::{Ty, TyCtxt, TypeckResults};
use rustc_span::symbol::{kw, Ident};
use rustc_span::{BytePos, Span};
Expand Down Expand Up @@ -853,12 +854,23 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)),
) => {
if tcx.res_generics_def_id(path.res) != Some(def.did()) {
bug!(
"unexpected path: def={:?} substs={:?} path={:?}",
def,
substs,
path,
);
match path.res {
Res::Def(DefKind::TyAlias, _) => {
// FIXME: Ideally we should support this. For that
// we have to map back from the self type to the
// type alias though. That's difficult.
//
// See the `need_type_info/type-alias.rs` test for
// some examples.
}
// There cannot be inference variables in the self type,
// so there's nothing for us to do here.
Res::SelfTy { .. } => {}
_ => warn!(
"unexpected path: def={:?} substs={:?} path={:?}",
def, substs, path,
),
}
} else {
return Box::new(
self.resolved_path_inferred_subst_iter(path, substs)
Expand Down Expand Up @@ -958,26 +970,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg))
{
let substs = self.infcx.resolve_vars_if_possible(substs);
let num_args = generics
.params
.iter()
.rev()
.filter(|&p| !matches!(p.kind, GenericParamDefKind::Lifetime))
.skip_while(|&param| {
if let Some(default) = param.default_value(tcx) {
// FIXME: Using structural comparisions has a bunch of false negatives.
//
// We should instead try to replace inference variables with placeholders and
// then use `infcx.can_eq`. That probably should be a separate method
// generally used during error reporting.
default.subst(tcx, substs) == substs[param.index as usize]
} else {
false
}
})
.count();
let generic_args =
&generics.own_substs(substs)[generics.own_counts().lifetimes..][..num_args];
let generic_args = &generics.own_substs_no_defaults(tcx, substs)
[generics.own_counts().lifetimes..];
let span = match expr.kind {
ExprKind::MethodCall(path, _, _) => path.ident.span,
_ => expr.span,
Expand Down
41 changes: 40 additions & 1 deletion compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,47 @@ impl<'tcx> Generics {
})
}

/// Returns the substs corresponding to the generic parameters
/// of this item, excluding `Self`.
///
/// **This should only be used for diagnostics purposes.**
pub fn own_substs_no_defaults(
&'tcx self,
tcx: TyCtxt<'tcx>,
substs: &'tcx [ty::GenericArg<'tcx>],
) -> &'tcx [ty::GenericArg<'tcx>] {
let mut own_params = self.parent_count..self.count();
if self.has_self && self.parent.is_none() {
own_params.start = 1;
}

// Filter the default arguments.
//
// This currently uses structural equality instead
// of semantic equivalance. While not ideal, that's
// good enough for now as this should only be used
// for diagnostics anyways.
own_params.end -= self
.params
.iter()
.rev()
.take_while(|param| {
param.default_value(tcx).map_or(false, |default| {
default.subst(tcx, substs) == substs[param.index as usize]
})
})
.count();

&substs[own_params]
}

/// Returns the substs corresponding to the generic parameters of this item, excluding `Self`.
pub fn own_substs(&'tcx self, substs: SubstsRef<'tcx>) -> &'tcx [ty::GenericArg<'tcx>] {
///
/// **This should only be used for diagnostics purposes.**
pub fn own_substs(
&'tcx self,
substs: &'tcx [ty::GenericArg<'tcx>],
) -> &'tcx [ty::GenericArg<'tcx>] {
let own = &substs[self.parent_count..][..self.params.len()];
if self.has_self && self.parent.is_none() { &own[1..] } else { &own }
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use crate::mir::{Body, GeneratorLayout};
use crate::traits::{self, Reveal};
use crate::ty;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::util::Discr;
pub use adt::*;
pub use assoc::*;
Expand All @@ -44,6 +43,7 @@ use rustc_session::cstore::CrateStoreDyn;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::abi::Align;
pub use subst::*;
pub use vtable::*;

use std::fmt::Debug;
Expand Down
39 changes: 1 addition & 38 deletions compiler/rustc_middle/src/ty/print/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ pub trait Printer<'tcx>: Sized {
// on top of the same path, but without its own generics.
_ => {
if !generics.params.is_empty() && substs.len() >= generics.count() {
let args = self.generic_args_to_print(generics, substs);
let args = generics.own_substs_no_defaults(self.tcx(), substs);
return self.path_generic_args(
|cx| cx.print_def_path(def_id, parent_substs),
args,
Expand Down Expand Up @@ -184,43 +184,6 @@ pub trait Printer<'tcx>: Sized {
}
}

fn generic_args_to_print(
&self,
generics: &'tcx ty::Generics,
substs: &'tcx [GenericArg<'tcx>],
) -> &'tcx [GenericArg<'tcx>] {
let mut own_params = generics.parent_count..generics.count();

// Don't print args for `Self` parameters (of traits).
if generics.has_self && own_params.start == 0 {
own_params.start = 1;
}

// Don't print args that are the defaults of their respective parameters.
own_params.end -= generics
.params
.iter()
.rev()
.take_while(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => false,
ty::GenericParamDefKind::Type { has_default, .. } => {
has_default
&& substs[param.index as usize]
== GenericArg::from(
self.tcx().bound_type_of(param.def_id).subst(self.tcx(), substs),
)
}
ty::GenericParamDefKind::Const { has_default } => {
has_default
&& substs[param.index as usize]
== GenericArg::from(self.tcx().const_param_default(param.def_id))
}
})
.count();

&substs[own_params]
}

fn default_print_impl_path(
self,
impl_def_id: DefId,
Expand Down
Loading

0 comments on commit 7092d42

Please sign in to comment.