mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-21 11:23:03 +00:00
Auto merge of #114076 - matthiaskrgr:rollup-cpqq1n9, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #112995 (Check for `<&NotClone as Clone>::clone()` calls and suggest to add Clone trait appropriately) - #113578 (Don't say that a type is uncallable if its fn signature has errors in it) - #113661 (Double check that hidden types match the expected hidden type) - #114044 (factor out more stable impls) - #114062 (CI: split nested GHA groups instead of panicking) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0dd5730e0f
@ -339,8 +339,8 @@ fn check_opaque_type_well_formed<'tcx>(
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
||||
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
|
||||
// tests to pass
|
||||
// This is fishy, but we check it again in `check_opaque_meets_bounds`.
|
||||
// Remove once we can prepopulate with known hidden types.
|
||||
let _ = infcx.take_opaque_types();
|
||||
|
||||
if errors.is_empty() {
|
||||
|
@ -56,8 +56,13 @@ pub fn is_subtype<'tcx>(
|
||||
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
|
||||
// we would get unification errors because we're unable to look into opaque types,
|
||||
// even if they're constrained in our current function.
|
||||
//
|
||||
// It seems very unlikely that this hides any bugs.
|
||||
let _ = infcx.take_opaque_types();
|
||||
for (key, ty) in infcx.take_opaque_types() {
|
||||
span_bug!(
|
||||
ty.hidden_type.span,
|
||||
"{}, {}",
|
||||
tcx.type_of(key.def_id).instantiate(tcx, key.args),
|
||||
ty.hidden_type.ty
|
||||
);
|
||||
}
|
||||
errors.is_empty()
|
||||
}
|
||||
|
@ -19,11 +19,13 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::traits::DefiningAnchor;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt,
|
||||
};
|
||||
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
|
||||
use rustc_span::symbol::sym;
|
||||
@ -34,6 +36,7 @@ use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplem
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _};
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
@ -437,7 +440,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
// hidden type is well formed even without those bounds.
|
||||
let predicate =
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into())));
|
||||
ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate));
|
||||
ocx.register_obligation(Obligation::new(tcx, misc_cause.clone(), param_env, predicate));
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
@ -464,11 +467,179 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
|
||||
}
|
||||
}
|
||||
// Clean up after ourselves
|
||||
let _ = infcx.take_opaque_types();
|
||||
// Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
|
||||
for (key, mut ty) in infcx.take_opaque_types() {
|
||||
ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
|
||||
sanity_check_found_hidden_type(tcx, key, ty.hidden_type, defining_use_anchor, origin)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sanity_check_found_hidden_type<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::OpaqueTypeKey<'tcx>,
|
||||
mut ty: ty::OpaqueHiddenType<'tcx>,
|
||||
defining_use_anchor: LocalDefId,
|
||||
origin: &hir::OpaqueTyOrigin,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if ty.ty.is_ty_var() {
|
||||
// Nothing was actually constrained.
|
||||
return Ok(());
|
||||
}
|
||||
if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() {
|
||||
if alias.def_id == key.def_id.to_def_id() && alias.args == key.args {
|
||||
// Nothing was actually constrained, this is an opaque usage that was
|
||||
// only discovered to be opaque after inference vars resolved.
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
// Closures frequently end up containing erased lifetimes in their final representation.
|
||||
// These correspond to lifetime variables that never got resolved, so we patch this up here.
|
||||
ty.ty = ty.ty.fold_with(&mut BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |t| t,
|
||||
ct_op: |c| c,
|
||||
lt_op: |l| match l.kind() {
|
||||
RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
|
||||
_ => l,
|
||||
},
|
||||
});
|
||||
// Get the hidden type.
|
||||
let mut hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
|
||||
if let hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) = origin {
|
||||
if hidden_ty != ty.ty {
|
||||
hidden_ty = find_and_apply_rpit_args(
|
||||
tcx,
|
||||
hidden_ty,
|
||||
defining_use_anchor.to_def_id(),
|
||||
key.def_id.to_def_id(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
// If the hidden types differ, emit a type mismatch diagnostic.
|
||||
if hidden_ty == ty.ty {
|
||||
Ok(())
|
||||
} else {
|
||||
let span = tcx.def_span(key.def_id);
|
||||
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
|
||||
Err(ty.report_mismatch(&other, key.def_id, tcx).emit())
|
||||
}
|
||||
}
|
||||
|
||||
/// In case it is in a nested opaque type, find that opaque type's
|
||||
/// usage in the function signature and use the generic arguments from the usage site.
|
||||
/// We need to do because RPITs ignore the lifetimes of the function,
|
||||
/// as they have their own copies of all the lifetimes they capture.
|
||||
/// So the only way to get the lifetimes represented in terms of the function,
|
||||
/// is to look how they are used in the function signature (or do some other fancy
|
||||
/// recording of this mapping at ast -> hir lowering time).
|
||||
///
|
||||
/// As an example:
|
||||
/// ```text
|
||||
/// trait Id {
|
||||
/// type Assoc;
|
||||
/// }
|
||||
/// impl<'a> Id for &'a () {
|
||||
/// type Assoc = &'a ();
|
||||
/// }
|
||||
/// fn func<'a>(x: &'a ()) -> impl Id<Assoc = impl Sized + 'a> { x }
|
||||
/// // desugared to
|
||||
/// fn func<'a>(x: &'a () -> Outer<'a> where <Outer<'a> as Id>::Assoc = Inner<'a> {
|
||||
/// // Note that in contrast to other nested items, RPIT type aliases can
|
||||
/// // access their parents' generics.
|
||||
///
|
||||
/// // hidden type is `&'aDupOuter ()`
|
||||
/// // During wfcheck the hidden type of `Inner<'aDupOuter>` is `&'a ()`, but
|
||||
/// // `typeof(Inner<'aDupOuter>) = &'aDupOuter ()`.
|
||||
/// // So we walk the signature of `func` to find the use of `Inner<'a>`
|
||||
/// // and then use that to replace the lifetimes in the hidden type, obtaining
|
||||
/// // `&'a ()`.
|
||||
/// type Outer<'aDupOuter> = impl Id<Assoc = Inner<'aDupOuter>>;
|
||||
///
|
||||
/// // hidden type is `&'aDupInner ()`
|
||||
/// type Inner<'aDupInner> = impl Sized + 'aDupInner;
|
||||
///
|
||||
/// x
|
||||
/// }
|
||||
/// ```
|
||||
fn find_and_apply_rpit_args<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut hidden_ty: Ty<'tcx>,
|
||||
function: DefId,
|
||||
opaque: DefId,
|
||||
) -> Result<Ty<'tcx>, ErrorGuaranteed> {
|
||||
// Find use of the RPIT in the function signature and thus find the right args to
|
||||
// convert it into the parameter space of the function signature. This is needed,
|
||||
// because that's what `type_of` returns, against which we compare later.
|
||||
let ret = tcx.fn_sig(function).instantiate_identity().output();
|
||||
struct Visitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaque: DefId,
|
||||
function: DefId,
|
||||
seen: FxHashSet<DefId>,
|
||||
}
|
||||
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> {
|
||||
type BreakTy = GenericArgsRef<'tcx>;
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
trace!("{:#?}", t.kind());
|
||||
match t.kind() {
|
||||
ty::Alias(ty::Opaque, alias) => {
|
||||
trace!(?alias.def_id);
|
||||
if alias.def_id == self.opaque {
|
||||
return ControlFlow::Break(alias.args);
|
||||
} else if self.seen.insert(alias.def_id) {
|
||||
for clause in self
|
||||
.tcx
|
||||
.explicit_item_bounds(alias.def_id)
|
||||
.iter_instantiated_copied(self.tcx, alias.args)
|
||||
{
|
||||
trace!(?clause);
|
||||
clause.visit_with(self)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Alias(ty::Projection, alias) => {
|
||||
if self.tcx.is_impl_trait_in_trait(alias.def_id)
|
||||
&& self.tcx.impl_trait_in_trait_parent_fn(alias.def_id) == self.function
|
||||
{
|
||||
// If we're lowering to associated item, install the opaque type which is just
|
||||
// the `type_of` of the trait's associated item. If we're using the old lowering
|
||||
// strategy, then just reinterpret the associated type like an opaque :^)
|
||||
self.tcx
|
||||
.type_of(alias.def_id)
|
||||
.instantiate(self.tcx, alias.args)
|
||||
.visit_with(self)?;
|
||||
}
|
||||
}
|
||||
ty::Alias(ty::Weak, alias) => {
|
||||
self.tcx
|
||||
.type_of(alias.def_id)
|
||||
.instantiate(self.tcx, alias.args)
|
||||
.visit_with(self)?;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
if let ControlFlow::Break(args) =
|
||||
ret.visit_with(&mut Visitor { tcx, function, opaque, seen: Default::default() })
|
||||
{
|
||||
trace!(?args);
|
||||
trace!("expected: {hidden_ty:#?}");
|
||||
hidden_ty = ty::EarlyBinder::bind(hidden_ty).instantiate(tcx, args);
|
||||
trace!("expected: {hidden_ty:#?}");
|
||||
} else {
|
||||
tcx.sess
|
||||
.delay_span_bug(tcx.def_span(function), format!("{ret:?} does not contain {opaque:?}"));
|
||||
}
|
||||
Ok(hidden_ty)
|
||||
}
|
||||
|
||||
fn is_enum_of_nonnullable_ptr<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
adt_def: AdtDef<'tcx>,
|
||||
|
@ -581,6 +581,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
callee_ty: Ty<'tcx>,
|
||||
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
||||
) -> ErrorGuaranteed {
|
||||
// Callee probe fails when APIT references errors, so suppress those
|
||||
// errors here.
|
||||
if let Some((_, _, args)) = self.extract_callable_info(callee_ty)
|
||||
&& let Err(err) = args.error_reported()
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
let mut unit_variant = None;
|
||||
if let hir::ExprKind::Path(qpath) = &callee_expr.kind
|
||||
&& let Res::Def(def::DefKind::Ctor(kind, CtorKind::Const), _)
|
||||
|
@ -1523,9 +1523,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
found_ty: Ty<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
) {
|
||||
// When `expr` is `x` in something like `let x = foo.clone(); x`, need to recurse up to get
|
||||
// `foo` and `clone`.
|
||||
let expr = self.note_type_is_not_clone_inner_expr(expr);
|
||||
|
||||
// If we've recursed to an `expr` of `foo.clone()`, get `foo` and `clone`.
|
||||
let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else {
|
||||
return;
|
||||
};
|
||||
@ -1578,6 +1584,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a type mismatch error caused by `&T` being cloned instead of `T`, and
|
||||
/// the `expr` as the source of this type mismatch, try to find the method call
|
||||
/// as the source of this error and return that instead. Otherwise, return the
|
||||
/// original expression.
|
||||
fn note_type_is_not_clone_inner_expr<'b>(
|
||||
&'b self,
|
||||
expr: &'b hir::Expr<'b>,
|
||||
) -> &'b hir::Expr<'b> {
|
||||
match expr.peel_blocks().kind {
|
||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { segments: [_], res: crate::Res::Local(binding), .. },
|
||||
)) => {
|
||||
let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.hir().find(*binding)
|
||||
else {
|
||||
return expr;
|
||||
};
|
||||
let Some(parent) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id)) else {
|
||||
return expr;
|
||||
};
|
||||
|
||||
match parent {
|
||||
// foo.clone()
|
||||
hir::Node::Local(hir::Local { init: Some(init), .. }) => {
|
||||
self.note_type_is_not_clone_inner_expr(init)
|
||||
}
|
||||
// When `expr` is more complex like a tuple
|
||||
hir::Node::Pat(hir::Pat {
|
||||
hir_id: pat_hir_id,
|
||||
kind: hir::PatKind::Tuple(pats, ..),
|
||||
..
|
||||
}) => {
|
||||
let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) =
|
||||
self.tcx.hir().find(self.tcx.hir().parent_id(*pat_hir_id)) else {
|
||||
return expr;
|
||||
};
|
||||
|
||||
match init.peel_blocks().kind {
|
||||
ExprKind::Tup(init_tup) => {
|
||||
if let Some(init) = pats
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|x| x.1.hir_id == *hir_id)
|
||||
.map(|(i, _)| init_tup.get(i).unwrap())
|
||||
.next()
|
||||
{
|
||||
self.note_type_is_not_clone_inner_expr(init)
|
||||
} else {
|
||||
expr
|
||||
}
|
||||
}
|
||||
_ => expr,
|
||||
}
|
||||
}
|
||||
_ => expr,
|
||||
}
|
||||
}
|
||||
// If we're calling into a closure that may not be typed recurse into that call. no need
|
||||
// to worry if it's a call to a typed function or closure as this would ne handled
|
||||
// previously.
|
||||
hir::ExprKind::Call(Expr { kind: call_expr_kind, .. }, _) => {
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, call_expr_path)) = call_expr_kind
|
||||
&& let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } = call_expr_path
|
||||
&& let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.hir().find(*binding)
|
||||
&& let Some(closure) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id))
|
||||
&& let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure
|
||||
&& let Expr { kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }), ..} = init
|
||||
{
|
||||
let hir::Body { value: body_expr, .. } = self.tcx.hir().body(*body_id);
|
||||
self.note_type_is_not_clone_inner_expr(body_expr)
|
||||
} else {
|
||||
expr
|
||||
}
|
||||
}
|
||||
_ => expr,
|
||||
}
|
||||
}
|
||||
|
||||
/// A common error is to add an extra semicolon:
|
||||
///
|
||||
/// ```compile_fail,E0308
|
||||
|
@ -575,19 +575,22 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
|
||||
impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
|
||||
type T = stable_mir::ty::GenericArgs;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::{GenericArgKind, GenericArgs};
|
||||
use stable_mir::ty::GenericArgs;
|
||||
|
||||
GenericArgs(
|
||||
self.iter()
|
||||
.map(|arg| match arg.unpack() {
|
||||
ty::GenericArgKind::Lifetime(region) => {
|
||||
GenericArgKind::Lifetime(opaque(®ion))
|
||||
}
|
||||
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(ty)),
|
||||
ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> {
|
||||
type T = stable_mir::ty::GenericArgKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::GenericArgKind;
|
||||
match self {
|
||||
ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(opaque(region)),
|
||||
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(*ty)),
|
||||
ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,63 +662,118 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
|
||||
type T = stable_mir::ty::BoundTyKind;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::BoundTyKind;
|
||||
|
||||
match self {
|
||||
ty::BoundTyKind::Anon => BoundTyKind::Anon,
|
||||
ty::BoundTyKind::Param(def_id, symbol) => {
|
||||
BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
|
||||
type T = stable_mir::ty::BoundRegionKind;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::BoundRegionKind;
|
||||
|
||||
match self {
|
||||
ty::BoundRegionKind::BrAnon(option_span) => {
|
||||
BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span)))
|
||||
}
|
||||
ty::BoundRegionKind::BrNamed(def_id, symbol) => {
|
||||
BoundRegionKind::BrNamed(rustc_internal::br_named_def(*def_id), symbol.to_string())
|
||||
}
|
||||
ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
|
||||
type T = stable_mir::ty::BoundVariableKind;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::{BoundRegionKind, BoundTyKind, BoundVariableKind};
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::BoundVariableKind;
|
||||
|
||||
match self {
|
||||
ty::BoundVariableKind::Ty(bound_ty_kind) => {
|
||||
BoundVariableKind::Ty(match bound_ty_kind {
|
||||
ty::BoundTyKind::Anon => BoundTyKind::Anon,
|
||||
ty::BoundTyKind::Param(def_id, symbol) => {
|
||||
BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string())
|
||||
}
|
||||
})
|
||||
BoundVariableKind::Ty(bound_ty_kind.stable(tables))
|
||||
}
|
||||
ty::BoundVariableKind::Region(bound_region_kind) => {
|
||||
BoundVariableKind::Region(match bound_region_kind {
|
||||
ty::BoundRegionKind::BrAnon(option_span) => {
|
||||
BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span)))
|
||||
}
|
||||
ty::BoundRegionKind::BrNamed(def_id, symbol) => BoundRegionKind::BrNamed(
|
||||
rustc_internal::br_named_def(*def_id),
|
||||
symbol.to_string(),
|
||||
),
|
||||
ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
|
||||
})
|
||||
BoundVariableKind::Region(bound_region_kind.stable(tables))
|
||||
}
|
||||
ty::BoundVariableKind::Const => BoundVariableKind::Const,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::IntTy {
|
||||
type T = IntTy;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::IntTy::Isize => IntTy::Isize,
|
||||
ty::IntTy::I8 => IntTy::I8,
|
||||
ty::IntTy::I16 => IntTy::I16,
|
||||
ty::IntTy::I32 => IntTy::I32,
|
||||
ty::IntTy::I64 => IntTy::I64,
|
||||
ty::IntTy::I128 => IntTy::I128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::UintTy {
|
||||
type T = UintTy;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::UintTy::Usize => UintTy::Usize,
|
||||
ty::UintTy::U8 => UintTy::U8,
|
||||
ty::UintTy::U16 => UintTy::U16,
|
||||
ty::UintTy::U32 => UintTy::U32,
|
||||
ty::UintTy::U64 => UintTy::U64,
|
||||
ty::UintTy::U128 => UintTy::U128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::FloatTy {
|
||||
type T = FloatTy;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::FloatTy::F32 => FloatTy::F32,
|
||||
ty::FloatTy::F64 => FloatTy::F64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for hir::Movability {
|
||||
type T = Movability;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
hir::Movability::Static => Movability::Static,
|
||||
hir::Movability::Movable => Movability::Movable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for Ty<'tcx> {
|
||||
type T = stable_mir::ty::TyKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self.kind() {
|
||||
ty::Bool => TyKind::RigidTy(RigidTy::Bool),
|
||||
ty::Char => TyKind::RigidTy(RigidTy::Char),
|
||||
ty::Int(int_ty) => match int_ty {
|
||||
ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)),
|
||||
ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)),
|
||||
ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)),
|
||||
ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)),
|
||||
ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)),
|
||||
ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)),
|
||||
},
|
||||
ty::Uint(uint_ty) => match uint_ty {
|
||||
ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)),
|
||||
ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)),
|
||||
ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)),
|
||||
ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)),
|
||||
ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)),
|
||||
ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)),
|
||||
},
|
||||
ty::Float(float_ty) => match float_ty {
|
||||
ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
|
||||
ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
|
||||
},
|
||||
ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))),
|
||||
ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))),
|
||||
ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))),
|
||||
ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
|
||||
rustc_internal::adt_def(adt_def.did()),
|
||||
generic_args.stable(tables),
|
||||
@ -758,10 +816,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
|
||||
ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
|
||||
rustc_internal::generator_def(*def_id),
|
||||
generic_args.stable(tables),
|
||||
match movability {
|
||||
hir::Movability::Static => Movability::Static,
|
||||
hir::Movability::Movable => Movability::Movable,
|
||||
},
|
||||
movability.stable(tables),
|
||||
)),
|
||||
ty::Never => TyKind::RigidTy(RigidTy::Never),
|
||||
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
|
||||
|
@ -272,6 +272,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
// assertions against dropping an `InferCtxt` without taking opaques.
|
||||
// FIXME: Once we remove support for the old impl we can remove this.
|
||||
if input.anchor != DefiningAnchor::Error {
|
||||
// This seems ok, but fragile.
|
||||
let _ = infcx.take_opaque_types();
|
||||
}
|
||||
|
||||
|
@ -36,25 +36,26 @@ impl CiEnv {
|
||||
}
|
||||
|
||||
pub mod gha {
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Mutex;
|
||||
|
||||
static GROUP_ACTIVE: AtomicBool = AtomicBool::new(false);
|
||||
static ACTIVE_GROUPS: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
||||
|
||||
/// All github actions log messages from this call to the Drop of the return value
|
||||
/// will be grouped and hidden by default in logs. Note that nesting these does
|
||||
/// not really work.
|
||||
/// will be grouped and hidden by default in logs. Note that since github actions doesn't
|
||||
/// support group nesting, any active group will be first finished when a subgroup is started,
|
||||
/// and then re-started when the subgroup finishes.
|
||||
#[track_caller]
|
||||
pub fn group(name: impl std::fmt::Display) -> Group {
|
||||
if std::env::var_os("GITHUB_ACTIONS").is_some() {
|
||||
eprintln!("::group::{name}");
|
||||
} else {
|
||||
eprintln!("{name}")
|
||||
let mut groups = ACTIVE_GROUPS.lock().unwrap();
|
||||
|
||||
// A group is currently active. End it first to avoid nesting.
|
||||
if !groups.is_empty() {
|
||||
end_group();
|
||||
}
|
||||
// https://github.com/actions/toolkit/issues/1001
|
||||
assert!(
|
||||
!GROUP_ACTIVE.swap(true, Ordering::Relaxed),
|
||||
"nested groups are not supported by GHA!"
|
||||
);
|
||||
|
||||
let name = name.to_string();
|
||||
start_group(&name);
|
||||
groups.push(name);
|
||||
Group(())
|
||||
}
|
||||
|
||||
@ -64,13 +65,36 @@ pub mod gha {
|
||||
|
||||
impl Drop for Group {
|
||||
fn drop(&mut self) {
|
||||
if std::env::var_os("GITHUB_ACTIONS").is_some() {
|
||||
eprintln!("::endgroup::");
|
||||
end_group();
|
||||
|
||||
let mut groups = ACTIVE_GROUPS.lock().unwrap();
|
||||
// Remove the current group
|
||||
groups.pop();
|
||||
|
||||
// If there was some previous group, restart it
|
||||
if is_in_gha() {
|
||||
if let Some(name) = groups.last() {
|
||||
start_group(format!("{name} (continued)"));
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
GROUP_ACTIVE.swap(false, Ordering::Relaxed),
|
||||
"group dropped but no group active!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn start_group(name: impl std::fmt::Display) {
|
||||
if is_in_gha() {
|
||||
eprintln!("::group::{name}");
|
||||
} else {
|
||||
eprintln!("{name}")
|
||||
}
|
||||
}
|
||||
|
||||
fn end_group() {
|
||||
if is_in_gha() {
|
||||
eprintln!("::endgroup::");
|
||||
}
|
||||
}
|
||||
|
||||
fn is_in_gha() -> bool {
|
||||
std::env::var_os("GITHUB_ACTIONS").is_some()
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
const ENTRY_LIMIT: usize = 900;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
const ISSUES_ENTRY_LIMIT: usize = 1894;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 1893;
|
||||
const ROOT_ENTRY_LIMIT: usize = 870;
|
||||
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
|
57
tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
Normal file
57
tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
Normal file
@ -0,0 +1,57 @@
|
||||
//! This test checks that we don't lose hidden types
|
||||
//! for *other* opaque types that we register and use
|
||||
//! to prove bounds while checking that a hidden type
|
||||
//! satisfies its opaque type's bounds.
|
||||
|
||||
#![feature(trivial_bounds, type_alias_impl_trait)]
|
||||
#![allow(trivial_bounds)]
|
||||
|
||||
mod sus {
|
||||
use super::*;
|
||||
pub type Sep = impl Sized + std::fmt::Display;
|
||||
//~^ ERROR: concrete type differs from previous defining opaque type use
|
||||
pub fn mk_sep() -> Sep {
|
||||
String::from("hello")
|
||||
}
|
||||
|
||||
pub trait Proj {
|
||||
type Assoc;
|
||||
}
|
||||
impl Proj for () {
|
||||
type Assoc = sus::Sep;
|
||||
}
|
||||
|
||||
pub struct Bar<T: Proj> {
|
||||
pub inner: <T as Proj>::Assoc,
|
||||
pub _marker: T,
|
||||
}
|
||||
impl<T: Proj> Clone for Bar<T> {
|
||||
fn clone(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
impl<T: Proj<Assoc = i32> + Copy> Copy for Bar<T> {}
|
||||
// This allows producing `Tait`s via `From`, even though
|
||||
// `define_tait` is not actually callable, and thus assumed
|
||||
// `Bar<()>: Copy` even though it isn't.
|
||||
pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
|
||||
pub fn define_tait() -> Tait
|
||||
where
|
||||
// this proves `Bar<()>: Copy`, but `define_tait` is
|
||||
// now uncallable
|
||||
(): Proj<Assoc = i32>,
|
||||
{
|
||||
Bar { inner: 1i32, _marker: () }
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_tait(x: sus::Tait) -> (sus::Tait, sus::Tait) {
|
||||
(x, x)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let bar = sus::Bar { inner: sus::mk_sep(), _marker: () };
|
||||
let (y, z) = copy_tait(bar.into()); // copy a string
|
||||
drop(y.into()); // drop one instance
|
||||
println!("{}", z.into().inner); // print the other
|
||||
}
|
14
tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
Normal file
14
tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/hidden_type_mismatch.rs:11:20
|
||||
|
|
||||
LL | pub type Sep = impl Sized + std::fmt::Display;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `String`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/hidden_type_mismatch.rs:37:21
|
||||
|
|
||||
LL | pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,7 +1,7 @@
|
||||
// check-pass
|
||||
|
||||
// Regression test for issue #83190, triggering an ICE in borrowck.
|
||||
|
||||
// check-pass
|
||||
|
||||
pub trait Any {}
|
||||
impl<T> Any for T {}
|
||||
|
8
tests/ui/typeck/apit-with-error-type-in-sig.rs
Normal file
8
tests/ui/typeck/apit-with-error-type-in-sig.rs
Normal file
@ -0,0 +1,8 @@
|
||||
type Foo = Bar;
|
||||
//~^ ERROR cannot find type `Bar` in this scope
|
||||
|
||||
fn check(f: impl FnOnce(Foo), val: Foo) {
|
||||
f(val);
|
||||
}
|
||||
|
||||
fn main() {}
|
9
tests/ui/typeck/apit-with-error-type-in-sig.stderr
Normal file
9
tests/ui/typeck/apit-with-error-type-in-sig.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0412]: cannot find type `Bar` in this scope
|
||||
--> $DIR/apit-with-error-type-in-sig.rs:1:12
|
||||
|
|
||||
LL | type Foo = Bar;
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0412`.
|
@ -11,3 +11,119 @@ fn clone_thing(nc: &NotClone) -> NotClone {
|
||||
//~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing2(nc: &NotClone) -> NotClone {
|
||||
let nc: NotClone = nc.clone();
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected due to this
|
||||
//~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
nc
|
||||
}
|
||||
|
||||
fn clone_thing3(nc: &NotClone) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let nc = nc.clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
nc
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing4(nc: &NotClone) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let nc = nc.clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
let nc2 = nc;
|
||||
nc2
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
impl NotClone {
|
||||
fn other_fn(&self) {}
|
||||
fn get_ref_notclone(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_thing5(nc: &NotClone) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let nc = nc.clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
let nc2 = nc;
|
||||
nc2.other_fn();
|
||||
let nc3 = nc2;
|
||||
nc3
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing6(nc: &NotClone) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let (ret, _) = (nc.clone(), 1);
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
let _ = nc.clone();
|
||||
ret
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing7(nc: Vec<&NotClone>) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let ret = nc[0].clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
ret
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing8(nc: &NotClone) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let ret = {
|
||||
let a = nc.clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
a
|
||||
};
|
||||
ret
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing9(nc: &NotClone) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let cl = || nc.clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
let ret = cl();
|
||||
ret
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing10(nc: &NotClone) -> (NotClone, NotClone) {
|
||||
let (a, b) = {
|
||||
let a = nc.clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
(a, nc.clone())
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
};
|
||||
(a, b)
|
||||
//~^ ERROR mismatched type
|
||||
//~| ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
||||
fn clone_thing11(nc: &NotClone) -> NotClone {
|
||||
//~^ NOTE expected `NotClone` because of return type
|
||||
let a = {
|
||||
let nothing = nc.clone();
|
||||
let a = nc.clone();
|
||||
//~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
let nothing = nc.clone();
|
||||
a
|
||||
};
|
||||
a
|
||||
//~^ ERROR mismatched type
|
||||
//~| NOTE expected `NotClone`, found `&NotClone`
|
||||
}
|
||||
|
@ -18,6 +18,219 @@ LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:16:24
|
||||
|
|
||||
LL | let nc: NotClone = nc.clone();
|
||||
| -------- ^^^^^^^^^^ expected `NotClone`, found `&NotClone`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:16:24
|
||||
|
|
||||
LL | let nc: NotClone = nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:28:5
|
||||
|
|
||||
LL | fn clone_thing3(nc: &NotClone) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | nc
|
||||
| ^^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:26:14
|
||||
|
|
||||
LL | let nc = nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:38:5
|
||||
|
|
||||
LL | fn clone_thing4(nc: &NotClone) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | nc2
|
||||
| ^^^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:35:14
|
||||
|
|
||||
LL | let nc = nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:57:5
|
||||
|
|
||||
LL | fn clone_thing5(nc: &NotClone) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | nc3
|
||||
| ^^^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:52:14
|
||||
|
|
||||
LL | let nc = nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:67:5
|
||||
|
|
||||
LL | fn clone_thing6(nc: &NotClone) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | ret
|
||||
| ^^^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:64:21
|
||||
|
|
||||
LL | let (ret, _) = (nc.clone(), 1);
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:76:5
|
||||
|
|
||||
LL | fn clone_thing7(nc: Vec<&NotClone>) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | ret
|
||||
| ^^^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:74:15
|
||||
|
|
||||
LL | let ret = nc[0].clone();
|
||||
| ^^^^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:88:5
|
||||
|
|
||||
LL | fn clone_thing8(nc: &NotClone) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | ret
|
||||
| ^^^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:84:17
|
||||
|
|
||||
LL | let a = nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:98:5
|
||||
|
|
||||
LL | fn clone_thing9(nc: &NotClone) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | ret
|
||||
| ^^^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:95:17
|
||||
|
|
||||
LL | let cl = || nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:110:6
|
||||
|
|
||||
LL | (a, b)
|
||||
| ^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:105:17
|
||||
|
|
||||
LL | let a = nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:110:9
|
||||
|
|
||||
LL | (a, b)
|
||||
| ^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:107:13
|
||||
|
|
||||
LL | (a, nc.clone())
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/explain_clone_autoref.rs:126:5
|
||||
|
|
||||
LL | fn clone_thing11(nc: &NotClone) -> NotClone {
|
||||
| -------- expected `NotClone` because of return type
|
||||
...
|
||||
LL | a
|
||||
| ^ expected `NotClone`, found `&NotClone`
|
||||
|
|
||||
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
||||
--> $DIR/explain_clone_autoref.rs:121:17
|
||||
|
|
||||
LL | let a = nc.clone();
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct NotClone;
|
||||
|
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
Loading…
Reference in New Issue
Block a user