Auto merge of #108339 - GuillaumeGomez:rollup-4z02kas, r=GuillaumeGomez

Rollup of 8 pull requests

Successful merges:

 - #108110 (Move some `InferCtxt` methods to `EvalCtxt` in new solver)
 - #108168 (Fix ICE on type alias in recursion)
 - #108230 (Convert a hard-warning about named static lifetimes into lint "unused_lifetimes")
 - #108239 (Fix overlapping spans in removing extra arguments)
 - #108246 (Add an InstCombine for redundant casts)
 - #108264 (no-fail-fast support for tool testsuites)
 - #108310 (rustdoc: Fix duplicated attributes for first reexport)
 - #108318 (Remove unused FileDesc::get_cloexec)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-02-22 12:04:45 +00:00
commit 3b4d6e0804
47 changed files with 563 additions and 401 deletions

View File

@ -18,6 +18,7 @@ use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::ty::{self, ir::TypeVisitor, DefIdTree, TyCtxt, TypeSuperVisitable};
use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
@ -923,17 +924,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
origin,
..
}) => {
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params
.iter()
.enumerate()
.map(|(late_bound_idx, param)| {
let pair = ResolvedArg::late(late_bound_idx as u32, param);
let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
(pair, r)
})
.unzip();
.iter()
.enumerate()
.map(|(late_bound_idx, param)| {
let pair = ResolvedArg::late(late_bound_idx as u32, param);
let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
(pair, r)
})
.unzip();
this.record_late_bound_vars(hir_id, binders.clone());
// Even if there are no lifetimes defined here, we still wrap it in a binder
// scope. If there happens to be a nested poly trait ref (an error), that
@ -968,20 +968,22 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
continue;
}
this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
this.tcx
.sess
.struct_span_warn(
lifetime.ident.span,
&format!(
"unnecessary lifetime parameter `{}`",
this.tcx.struct_span_lint_hir(
lint::builtin::UNUSED_LIFETIMES,
lifetime.hir_id,
lifetime.ident.span,
format!(
"unnecessary lifetime parameter `{}`",
lifetime.ident
),
|lint| {
let help = &format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime.ident,
),
)
.help(&format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime.ident,
))
.emit();
);
lint.help(help)
},
);
}
}
}

View File

@ -932,25 +932,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
labels
.push((provided_span, format!("unexpected argument{}", provided_ty_name)));
let mut span = provided_span;
if arg_idx.index() > 0
if span.can_be_used_for_suggestions() {
if arg_idx.index() > 0
&& let Some((_, prev)) = provided_arg_tys
.get(ProvidedIdx::from_usize(arg_idx.index() - 1)
) {
// Include previous comma
span = span.with_lo(prev.hi());
} else if let Some((_, next)) = provided_arg_tys.get(
ProvidedIdx::from_usize(arg_idx.index() + 1),
) {
// Include next comma
span = span.until(*next);
span = prev.shrink_to_hi().to(span);
}
suggestions.push((span, String::new()));
suggestions.push((span, String::new()));
suggestion_text = match suggestion_text {
SuggestionText::None => SuggestionText::Remove(false),
SuggestionText::Remove(_) => SuggestionText::Remove(true),
_ => SuggestionText::DidYouMean,
};
suggestion_text = match suggestion_text {
SuggestionText::None => SuggestionText::Remove(false),
SuggestionText::Remove(_) => SuggestionText::Remove(true),
_ => SuggestionText::DidYouMean,
};
}
}
Error::Missing(expected_idx) => {
// If there are multiple missing arguments adjacent to each other,

View File

@ -2,7 +2,7 @@ use crate::dep_graph::DepKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::Representability;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_query_system::query::QueryInfo;
@ -199,7 +199,8 @@ fn find_item_ty_spans(
) {
match ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
if let Some(def_id) = path.res.opt_def_id() {
if let Res::Def(kind, def_id) = path.res
&& kind != DefKind::TyAlias {
let check_params = def_id.as_local().map_or(true, |def_id| {
if def_id == needle {
spans.push(ty.span);

View File

@ -30,6 +30,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
ctx.combine_bool_cmp(&statement.source_info, rvalue);
ctx.combine_ref_deref(&statement.source_info, rvalue);
ctx.combine_len(&statement.source_info, rvalue);
ctx.combine_cast(&statement.source_info, rvalue);
}
_ => {}
}
@ -142,6 +143,14 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
}
}
fn combine_cast(&self, _source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Cast(_kind, operand, ty) = rvalue {
if operand.ty(self.local_decls, self.tcx) == *ty {
*rvalue = Rvalue::Use(operand.clone());
}
}
}
fn combine_primitive_clone(
&self,
terminator: &mut Terminator<'tcx>,

View File

@ -1,6 +1,5 @@
//! Code shared by trait and projection goals for candidate assembly.
use super::infcx_ext::InferCtxtExt;
#[cfg(doc)]
use super::trait_goals::structural_traits::*;
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
@ -206,7 +205,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
&mut self,
goal: Goal<'tcx, G>,
) -> Vec<Candidate<'tcx>> {
debug_assert_eq!(goal, self.infcx.resolve_vars_if_possible(goal));
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
// HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
// object bound, alias bound, etc. We are unable to determine this until we can at
@ -250,8 +249,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let &ty::Alias(ty::Projection, projection_ty) = goal.predicate.self_ty().kind() else {
return
};
self.infcx.probe(|_| {
let normalized_ty = self.infcx.next_ty_infer();
self.probe(|this| {
let normalized_ty = this.next_ty_infer();
let normalizes_to_goal = goal.with(
tcx,
ty::Binder::dummy(ty::ProjectionPredicate {
@ -259,16 +258,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
term: normalized_ty.into(),
}),
);
let normalization_certainty = match self.evaluate_goal(normalizes_to_goal) {
let normalization_certainty = match this.evaluate_goal(normalizes_to_goal) {
Ok((_, certainty)) => certainty,
Err(NoSolution) => return,
};
let normalized_ty = self.infcx.resolve_vars_if_possible(normalized_ty);
let normalized_ty = this.resolve_vars_if_possible(normalized_ty);
// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
// This doesn't work as long as we use `CandidateSource` in winnowing.
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
let normalized_candidates = self.assemble_and_evaluate_candidates(goal);
let normalized_candidates = this.assemble_and_evaluate_candidates(goal);
for mut normalized_candidate in normalized_candidates {
normalized_candidate.result =
normalized_candidate.result.unchecked_map(|mut response| {

View File

@ -0,0 +1,172 @@
use rustc_hir::def_id::DefId;
use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::{self, ir::TypeVisitor, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable};
use rustc_span::DUMMY_SP;
use std::ops::ControlFlow;
use super::search_graph::SearchGraph;
use super::Goal;
pub struct EvalCtxt<'a, 'tcx> {
// FIXME: should be private.
pub(super) infcx: &'a InferCtxt<'tcx>,
pub(super) var_values: CanonicalVarValues<'tcx>,
pub(super) search_graph: &'a mut SearchGraph<'tcx>,
/// This field is used by a debug assertion in [`EvalCtxt::evaluate_goal`],
/// see the comment in that method for more details.
pub in_projection_eq_hack: bool,
}
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn probe<T>(&mut self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T) -> T {
self.infcx.probe(|_| f(self))
}
pub(super) fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
pub(super) fn next_ty_infer(&self) -> Ty<'tcx> {
self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: DUMMY_SP,
})
}
pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
self.infcx.next_const_var(
ty,
ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span: DUMMY_SP },
)
}
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
///
/// This is the case if the `term` is an inference variable in the innermost universe
/// and does not occur in any other part of the predicate.
pub(super) fn term_is_fully_unconstrained(
&self,
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
) -> bool {
let term_is_infer = match goal.predicate.term.unpack() {
ty::TermKind::Ty(ty) => {
if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
match self.infcx.probe_ty_var(vid) {
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
Err(universe) => universe == self.universe(),
}
} else {
false
}
}
ty::TermKind::Const(ct) => {
if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
match self.infcx.probe_const_var(vid) {
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
Err(universe) => universe == self.universe(),
}
} else {
false
}
}
};
// Guard against `<T as Trait<?0>>::Assoc = ?0>`.
struct ContainsTerm<'tcx> {
term: ty::Term<'tcx>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTerm<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.needs_infer() {
if ty::Term::from(t) == self.term {
ControlFlow::Break(())
} else {
t.super_visit_with(self)
}
} else {
ControlFlow::Continue(())
}
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if c.needs_infer() {
if ty::Term::from(c) == self.term {
ControlFlow::Break(())
} else {
c.super_visit_with(self)
}
} else {
ControlFlow::Continue(())
}
}
}
let mut visitor = ContainsTerm { term: goal.predicate.term };
term_is_infer
&& goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
&& goal.param_env.visit_with(&mut visitor).is_continue()
}
#[instrument(level = "debug", skip(self, param_env), ret)]
pub(super) fn eq<T: ToTrace<'tcx>>(
&self,
param_env: ty::ParamEnv<'tcx>,
lhs: T,
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.eq(lhs, rhs)
.map(|InferOk { value: (), obligations }| {
obligations.into_iter().map(|o| o.into()).collect()
})
.map_err(|e| {
debug!(?e, "failed to equate");
NoSolution
})
}
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<'tcx> + Copy>(
&self,
value: ty::Binder<'tcx, T>,
) -> T {
self.infcx.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::HigherRankedType,
value,
)
}
pub(super) fn instantiate_binder_with_placeholders<T: TypeFoldable<'tcx> + Copy>(
&self,
value: ty::Binder<'tcx, T>,
) -> T {
self.infcx.instantiate_binder_with_placeholders(value)
}
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
self.infcx.resolve_vars_if_possible(value)
}
pub(super) fn fresh_substs_for_item(&self, def_id: DefId) -> ty::SubstsRef<'tcx> {
self.infcx.fresh_substs_for_item(DUMMY_SP, def_id)
}
pub(super) fn universe(&self) -> ty::UniverseIndex {
self.infcx.universe()
}
}

View File

@ -1,77 +0,0 @@
use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_span::DUMMY_SP;
use super::Goal;
/// Methods used inside of the canonical queries of the solver.
///
/// Most notably these do not care about diagnostics information.
/// If you find this while looking for methods to use outside of the
/// solver, you may look at the implementation of these method for
/// help.
pub(super) trait InferCtxtExt<'tcx> {
fn next_ty_infer(&self) -> Ty<'tcx>;
fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx>;
fn eq<T: ToTrace<'tcx>>(
&self,
param_env: ty::ParamEnv<'tcx>,
lhs: T,
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>;
fn instantiate_binder_with_infer<T: TypeFoldable<'tcx> + Copy>(
&self,
value: ty::Binder<'tcx, T>,
) -> T;
}
impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn next_ty_infer(&self) -> Ty<'tcx> {
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: DUMMY_SP,
})
}
fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
self.next_const_var(
ty,
ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span: DUMMY_SP },
)
}
#[instrument(level = "debug", skip(self, param_env), ret)]
fn eq<T: ToTrace<'tcx>>(
&self,
param_env: ty::ParamEnv<'tcx>,
lhs: T,
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.at(&ObligationCause::dummy(), param_env)
.eq(lhs, rhs)
.map(|InferOk { value: (), obligations }| {
obligations.into_iter().map(|o| o.into()).collect()
})
.map_err(|e| {
debug!(?e, "failed to equate");
NoSolution
})
}
fn instantiate_binder_with_infer<T: TypeFoldable<'tcx> + Copy>(
&self,
value: ty::Binder<'tcx, T>,
) -> T {
self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::HigherRankedType,
value,
)
}
}

View File

@ -35,16 +35,15 @@ use crate::solve::search_graph::OverflowHandler;
use crate::traits::ObligationCause;
mod assembly;
mod eval_ctxt;
mod fulfill;
mod infcx_ext;
mod project_goals;
mod search_graph;
mod trait_goals;
pub use eval_ctxt::EvalCtxt;
pub use fulfill::FulfillmentCtxt;
use self::infcx_ext::InferCtxtExt;
/// A goal is a statement, i.e. `predicate`, we want to prove
/// given some assumptions, i.e. `param_env`.
///
@ -180,22 +179,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
}
}
struct EvalCtxt<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
var_values: CanonicalVarValues<'tcx>,
search_graph: &'a mut search_graph::SearchGraph<'tcx>,
/// This field is used by a debug assertion in [`EvalCtxt::evaluate_goal`],
/// see the comment in that method for more details.
in_projection_eq_hack: bool,
}
impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
/// The entry point of the solver.
///
/// This function deals with (coinductive) cycles, overflow, and caching
@ -427,7 +411,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other| {
debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other);
let r = ecx.infcx.probe(|_| {
let r = ecx.probe(|ecx| {
let (_, certainty) = ecx.evaluate_goal(goal.with(
tcx,
ty::Binder::dummy(ty::ProjectionPredicate {
@ -462,10 +446,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// Evaluate all 3 potential candidates for the alias' being equal
candidates.push(evaluate_normalizes_to(self, alias_lhs, goal.predicate.1));
candidates.push(evaluate_normalizes_to(self, alias_rhs, goal.predicate.0));
candidates.push(self.infcx.probe(|_| {
candidates.push(self.probe(|this| {
debug!("compute_alias_eq_goal: alias defids are equal, equating substs");
let nested_goals = self.infcx.eq(goal.param_env, alias_lhs, alias_rhs)?;
self.evaluate_all_and_make_canonical_response(nested_goals)
let nested_goals = this.eq(goal.param_env, alias_lhs, alias_rhs)?;
this.evaluate_all_and_make_canonical_response(nested_goals)
}));
debug!(?candidates);
@ -481,7 +465,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
) -> QueryResult<'tcx> {
let (ct, ty) = goal.predicate;
let nested_goals = self.infcx.eq(goal.param_env, ct.ty(), ty)?;
let nested_goals = self.eq(goal.param_env, ct.ty(), ty)?;
self.evaluate_all_and_make_canonical_response(nested_goals)
}
}

View File

@ -1,7 +1,6 @@
use crate::traits::{specialization_graph, translate_substs};
use super::assembly;
use super::infcx_ext::InferCtxtExt;
use super::trait_goals::structural_traits;
use super::{Certainty, EvalCtxt, Goal, QueryResult};
use rustc_errors::ErrorGuaranteed;
@ -13,12 +12,11 @@ use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::specialization_graph::LeafDef;
use rustc_infer::traits::Reveal;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::ProjectionPredicate;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ir::TypeVisitor, ProjectionPredicate, TypeSuperVisitable};
use rustc_middle::ty::{ToPredicate, TypeVisitable};
use rustc_span::{sym, DUMMY_SP};
use std::iter;
use std::ops::ControlFlow;
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn compute_projection_goal(
@ -38,8 +36,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
} else {
let predicate = goal.predicate;
let unconstrained_rhs = match predicate.term.unpack() {
ty::TermKind::Ty(_) => self.infcx.next_ty_infer().into(),
ty::TermKind::Const(ct) => self.infcx.next_const_infer(ct.ty()).into(),
ty::TermKind::Ty(_) => self.next_ty_infer().into(),
ty::TermKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
};
let unconstrained_predicate = ty::Clause::Projection(ProjectionPredicate {
projection_ty: goal.predicate.projection_ty,
@ -49,8 +47,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
this.evaluate_goal(goal.with(this.tcx(), unconstrained_predicate))
})?;
let nested_eq_goals =
self.infcx.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
let nested_eq_goals = self.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
let eval_certainty = self.evaluate_all(nested_eq_goals)?;
self.make_canonical_response(normalize_certainty.unify_and(eval_certainty))
}
@ -65,73 +62,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
result
}
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
///
/// This is the case if the `term` is an inference variable in the innermost universe
/// and does not occur in any other part of the predicate.
fn term_is_fully_unconstrained(&self, goal: Goal<'tcx, ProjectionPredicate<'tcx>>) -> bool {
let infcx = self.infcx;
let term_is_infer = match goal.predicate.term.unpack() {
ty::TermKind::Ty(ty) => {
if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
match infcx.probe_ty_var(vid) {
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
Err(universe) => universe == infcx.universe(),
}
} else {
false
}
}
ty::TermKind::Const(ct) => {
if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
match self.infcx.probe_const_var(vid) {
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
Err(universe) => universe == infcx.universe(),
}
} else {
false
}
}
};
// Guard against `<T as Trait<?0>>::Assoc = ?0>`.
struct ContainsTerm<'tcx> {
term: ty::Term<'tcx>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTerm<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.needs_infer() {
if ty::Term::from(t) == self.term {
ControlFlow::Break(())
} else {
t.super_visit_with(self)
}
} else {
ControlFlow::Continue(())
}
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if c.needs_infer() {
if ty::Term::from(c) == self.term {
ControlFlow::Break(())
} else {
c.super_visit_with(self)
}
} else {
ControlFlow::Continue(())
}
}
}
let mut visitor = ContainsTerm { term: goal.predicate.term };
term_is_infer
&& goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
&& goal.param_env.visit_with(&mut visitor).is_continue()
}
/// After normalizing the projection to `normalized_alias` with the given
/// `normalization_certainty`, constrain the inference variable `term` to it
/// and return a query response.
@ -145,7 +75,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
//
// It can however be ambiguous when the `normalized_alias` contains a projection.
let nested_goals = self
.infcx
.eq(goal.param_env, goal.predicate.term, normalized_alias.into())
.expect("failed to unify with unconstrained term");
let rhs_certainty =
@ -177,10 +106,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
&& poly_projection_pred.projection_def_id() == goal.predicate.def_id()
{
ecx.infcx.probe(|_| {
ecx.probe(|ecx| {
let assumption_projection_pred =
ecx.infcx.instantiate_binder_with_infer(poly_projection_pred);
let mut nested_goals = ecx.infcx.eq(
ecx.instantiate_binder_with_infer(poly_projection_pred);
let mut nested_goals = ecx.eq(
goal.param_env,
goal.predicate.projection_ty,
assumption_projection_pred.projection_ty,
@ -215,11 +144,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
return Err(NoSolution);
}
ecx.infcx.probe(|_| {
let impl_substs = ecx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
ecx.probe(|ecx| {
let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
let mut nested_goals = ecx.infcx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
let mut nested_goals = ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
let where_clause_bounds = tcx
.predicates_of(impl_def_id)
.instantiate(tcx, impl_substs)
@ -367,7 +296,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
let tcx = ecx.tcx();
ecx.infcx.probe(|_| {
ecx.probe(|ecx| {
let metadata_ty = match goal.predicate.self_ty().kind() {
ty::Bool
| ty::Char
@ -546,8 +475,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx());
ecx.infcx
.probe(|_| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant))
ecx.probe(|ecx| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant))
}
}

View File

@ -3,11 +3,9 @@
use std::iter;
use super::assembly;
use super::infcx_ext::InferCtxtExt;
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::util::supertraits;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@ -45,12 +43,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
return Err(NoSolution);
}
ecx.infcx.probe(|_| {
let impl_substs = ecx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
ecx.probe(|ecx| {
let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
let mut nested_goals =
ecx.infcx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
let where_clause_bounds = tcx
.predicates_of(impl_def_id)
.instantiate(tcx, impl_substs)
@ -72,10 +70,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
&& poly_trait_pred.def_id() == goal.predicate.def_id()
{
// FIXME: Constness and polarity
ecx.infcx.probe(|_| {
ecx.probe(|ecx| {
let assumption_trait_pred =
ecx.infcx.instantiate_binder_with_infer(poly_trait_pred);
let mut nested_goals = ecx.infcx.eq(
ecx.instantiate_binder_with_infer(poly_trait_pred);
let mut nested_goals = ecx.eq(
goal.param_env,
goal.predicate.trait_ref,
assumption_trait_pred.trait_ref,
@ -118,7 +116,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
) -> QueryResult<'tcx> {
let tcx = ecx.tcx();
ecx.infcx.probe(|_| {
ecx.probe(|ecx| {
let nested_obligations = tcx
.predicates_of(goal.predicate.def_id())
.instantiate(tcx, goal.predicate.trait_ref.substs);
@ -275,7 +273,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
if b_ty.is_ty_var() {
return ecx.make_canonical_response(Certainty::AMBIGUOUS);
}
ecx.infcx.probe(|_| {
ecx.probe(|ecx| {
match (a_ty.kind(), b_ty.kind()) {
// Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
(&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => {
@ -318,7 +316,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// `[T; n]` -> `[T]` unsizing
(&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => {
// We just require that the element type stays the same
let nested_goals = ecx.infcx.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
let nested_goals = ecx.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
ecx.evaluate_all_and_make_canonical_response(nested_goals)
}
// Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
@ -352,7 +350,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// Finally, we require that `TailA: Unsize<TailB>` for the tail field
// types.
let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
let mut nested_goals = ecx.eq(goal.param_env, unsized_a_ty, b_ty)?;
nested_goals.push(goal.with(
tcx,
ty::Binder::dummy(
@ -371,7 +369,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// Substitute just the tail field of B., and require that they're equal.
let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty]).copied());
let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
let mut nested_goals = ecx.eq(goal.param_env, unsized_a_ty, b_ty)?;
// Similar to ADTs, require that the rest of the fields are equal.
nested_goals.push(goal.with(
@ -411,7 +409,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
}
let mut unsize_dyn_to_principal = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
ecx.infcx.probe(|_| -> Result<_, NoSolution> {
ecx.probe(|ecx| -> Result<_, NoSolution> {
// Require that all of the trait predicates from A match B, except for
// the auto traits. We do this by constructing a new A type with B's
// auto traits, and equating these types.
@ -431,7 +429,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn);
// We also require that A's lifetime outlives B's lifetime.
let mut nested_obligations = ecx.infcx.eq(goal.param_env, new_a_ty, b_ty)?;
let mut nested_obligations = ecx.eq(goal.param_env, new_a_ty, b_ty)?;
nested_obligations.push(
goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))),
);
@ -482,16 +480,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
fn probe_and_evaluate_goal_for_constituent_tys(
&mut self,
goal: Goal<'tcx, TraitPredicate<'tcx>>,
constituent_tys: impl Fn(&InferCtxt<'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>,
constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>,
) -> QueryResult<'tcx> {
self.infcx.probe(|_| {
self.evaluate_all_and_make_canonical_response(
constituent_tys(self.infcx, goal.predicate.self_ty())?
self.probe(|this| {
this.evaluate_all_and_make_canonical_response(
constituent_tys(this, goal.predicate.self_ty())?
.into_iter()
.map(|ty| {
goal.with(
self.tcx(),
ty::Binder::dummy(goal.predicate.with_self_ty(self.tcx(), ty)),
this.tcx(),
ty::Binder::dummy(goal.predicate.with_self_ty(this.tcx(), ty)),
)
})
.collect(),

View File

@ -1,16 +1,18 @@
use rustc_hir::{Movability, Mutability};
use rustc_infer::{infer::InferCtxt, traits::query::NoSolution};
use rustc_infer::traits::query::NoSolution;
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::solve::EvalCtxt;
// Calculates the constituent types of a type for `auto trait` purposes.
//
// For types with an "existential" binder, i.e. generator witnesses, we also
// instantiate the binder with placeholders eagerly.
pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
infcx: &InferCtxt<'tcx>,
ecx: &EvalCtxt<'_, 'tcx>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
let tcx = infcx.tcx;
let tcx = ecx.tcx();
match *ty.kind() {
ty::Uint(_)
| ty::Int(_)
@ -53,9 +55,7 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
Ok(vec![generator_substs.tupled_upvars_ty(), generator_substs.witness()])
}
ty::GeneratorWitness(types) => {
Ok(infcx.instantiate_binder_with_placeholders(types).to_vec())
}
ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
ty::GeneratorWitnessMIR(..) => todo!(),
@ -74,7 +74,7 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
}
pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
infcx: &InferCtxt<'tcx>,
ecx: &EvalCtxt<'_, 'tcx>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
match *ty.kind() {
@ -113,18 +113,18 @@ pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
ty::Tuple(tys) => Ok(tys.to_vec()),
ty::Adt(def, substs) => {
let sized_crit = def.sized_constraint(infcx.tcx);
let sized_crit = def.sized_constraint(ecx.tcx());
Ok(sized_crit
.0
.iter()
.map(|ty| sized_crit.rebind(*ty).subst(infcx.tcx, substs))
.map(|ty| sized_crit.rebind(*ty).subst(ecx.tcx(), substs))
.collect())
}
}
}
pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
infcx: &InferCtxt<'tcx>,
ecx: &EvalCtxt<'_, 'tcx>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
match *ty.kind() {
@ -165,7 +165,7 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
ty::Closure(_, substs) => Ok(vec![substs.as_closure().tupled_upvars_ty()]),
ty::Generator(_, substs, Movability::Movable) => {
if infcx.tcx.features().generator_clone {
if ecx.tcx().features().generator_clone {
let generator = substs.as_generator();
Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
} else {
@ -173,9 +173,7 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
}
}
ty::GeneratorWitness(types) => {
Ok(infcx.instantiate_binder_with_placeholders(types).to_vec())
}
ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
ty::GeneratorWitnessMIR(..) => todo!(),
}

View File

@ -197,11 +197,6 @@ impl FileDesc {
}
}
#[cfg(target_os = "linux")]
pub fn get_cloexec(&self) -> io::Result<bool> {
unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
}
#[cfg(not(any(
target_env = "newlib",
target_os = "solaris",

View File

@ -435,6 +435,10 @@ impl Step for Rustfmt {
&[],
);
if !builder.fail_fast {
cargo.arg("--no-fail-fast");
}
let dir = testdir(builder, compiler.host);
t!(fs::create_dir_all(&dir));
cargo.env("RUSTFMT_TEST_DIR", dir);
@ -615,6 +619,10 @@ impl Step for Miri {
);
cargo.add_rustc_lib_path(builder, compiler);
if !builder.fail_fast {
cargo.arg("--no-fail-fast");
}
// miri tests need to know about the stage sysroot
cargo.env("MIRI_SYSROOT", &miri_sysroot);
cargo.env("MIRI_HOST_SYSROOT", sysroot);
@ -746,6 +754,10 @@ impl Step for Clippy {
&[],
);
if !builder.fail_fast {
cargo.arg("--no-fail-fast");
}
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());

View File

@ -2114,17 +2114,29 @@ fn get_all_import_attributes<'hir>(
attributes: &mut Vec<ast::Attribute>,
is_inline: bool,
) {
let mut first = true;
let hir_map = tcx.hir();
let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
let mut visited = FxHashSet::default();
// If the item is an import and has at least a path with two parts, we go into it.
while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) {
// We add the attributes from this import into the list.
add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
if first {
// This is the "original" reexport so we get all its attributes without filtering them.
attributes.extend_from_slice(hir_map.attrs(item.hir_id()));
first = false;
} else {
add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
}
let def_id = if path.segments.len() > 1 {
match path.segments[path.segments.len() - 2].res {
let def_id = if let [.., parent_segment, _] = &path.segments {
match parent_segment.res {
hir::def::Res::Def(_, def_id) => def_id,
_ if parent_segment.ident.name == kw::Crate => {
// In case the "parent" is the crate, it'll give `Res::Err` so we need to
// circumvent it this way.
tcx.parent(item.owner_id.def_id.to_def_id())
}
_ => break,
}
} else {
@ -2341,9 +2353,7 @@ fn clean_maybe_renamed_item<'tcx>(
if let Some(import_id) = import_id &&
let Some(hir::Node::Item(use_node)) = cx.tcx.hir().find_by_def_id(import_id)
{
// First, we add the attributes from the current import.
extra_attrs.extend_from_slice(inline::load_attrs(cx, import_id.to_def_id()));
let is_inline = extra_attrs.lists(sym::doc).get_word_attr(sym::inline).is_some();
let is_inline = inline::load_attrs(cx, import_id.to_def_id()).lists(sym::doc).get_word_attr(sym::inline).is_some();
// Then we get all the various imports' attributes.
get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs, is_inline);
add_without_unwanted_attributes(&mut extra_attrs, inline::load_attrs(cx, def_id), is_inline);

View File

@ -0,0 +1,25 @@
- // MIR for `redundant` before InstCombine
+ // MIR for `redundant` after InstCombine
fn redundant(_1: *const &u8) -> *const &u8 {
debug x => _1; // in scope 0 at $DIR/casts.rs:+0:30: +0:31
let mut _0: *const &u8; // return place in scope 0 at $DIR/casts.rs:+0:51: +0:64
let mut _2: *const &u8; // in scope 0 at $DIR/casts.rs:+1:5: +1:55
let mut _3: *const &u8; // in scope 0 at $DIR/casts.rs:+1:36: +1:37
scope 1 (inlined generic_cast::<&u8, &u8>) { // at $DIR/casts.rs:6:5: 6:38
debug x => _3; // in scope 1 at $DIR/casts.rs:10:23: 10:24
}
bb0: {
StorageLive(_2); // scope 0 at $DIR/casts.rs:+1:5: +1:55
StorageLive(_3); // scope 0 at $DIR/casts.rs:+1:36: +1:37
_3 = _1; // scope 0 at $DIR/casts.rs:+1:36: +1:37
- _2 = _3 as *const &u8 (PtrToPtr); // scope 1 at $DIR/casts.rs:11:5: 11:18
+ _2 = _3; // scope 1 at $DIR/casts.rs:11:5: 11:18
StorageDead(_3); // scope 0 at $DIR/casts.rs:+1:37: +1:38
_0 = _2; // scope 0 at $DIR/casts.rs:+1:5: +1:55
StorageDead(_2); // scope 0 at $DIR/casts.rs:+2:1: +2:2
return; // scope 0 at $DIR/casts.rs:+2:2: +2:2
}
}

View File

@ -0,0 +1,14 @@
// MIR for `redundant` after PreCodegen
fn redundant(_1: *const &u8) -> *const &u8 {
debug x => _1; // in scope 0 at $DIR/casts.rs:+0:30: +0:31
let mut _0: *const &u8; // return place in scope 0 at $DIR/casts.rs:+0:51: +0:64
scope 1 (inlined generic_cast::<&u8, &u8>) { // at $DIR/casts.rs:6:5: 6:38
debug x => _1; // in scope 1 at $DIR/casts.rs:10:23: 10:24
}
bb0: {
_0 = _1; // scope 0 at $DIR/casts.rs:+1:5: +1:55
return; // scope 0 at $DIR/casts.rs:+2:2: +2:2
}
}

View File

@ -0,0 +1,15 @@
// MIR for `roundtrip` after PreCodegen
fn roundtrip(_1: *const u8) -> *const u8 {
debug x => _1; // in scope 0 at $DIR/casts.rs:+0:18: +0:19
let mut _0: *const u8; // return place in scope 0 at $DIR/casts.rs:+0:35: +0:44
let mut _2: *mut u8; // in scope 0 at $DIR/casts.rs:+1:5: +1:17
bb0: {
StorageLive(_2); // scope 0 at $DIR/casts.rs:+1:5: +1:17
_2 = _1 as *mut u8 (PtrToPtr); // scope 0 at $DIR/casts.rs:+1:5: +1:17
_0 = move _2 as *const u8 (Pointer(MutToConstPointer)); // scope 0 at $DIR/casts.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/casts.rs:+1:16: +1:17
return; // scope 0 at $DIR/casts.rs:+2:2: +2:2
}
}

17
tests/mir-opt/casts.rs Normal file
View File

@ -0,0 +1,17 @@
#![crate_type = "lib"]
// EMIT_MIR casts.redundant.InstCombine.diff
// EMIT_MIR casts.redundant.PreCodegen.after.mir
pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 {
generic_cast::<&'a u8, &'b u8>(x) as *const &'a u8
}
#[inline]
fn generic_cast<T, U>(x: *const T) -> *const U {
x as *const U
}
// EMIT_MIR casts.roundtrip.PreCodegen.after.mir
pub fn roundtrip(x: *const u8) -> *const u8 {
x as *mut u8 as *const u8
}

View File

@ -0,0 +1,25 @@
// Regression test for <https://github.com/rust-lang/rust/issues/108281>.
// It ensures that the attributes on the first reexport are not duplicated.
#![crate_name = "foo"]
// @has 'foo/index.html'
#[doc(hidden)]
pub fn bar() {}
mod sub {
pub fn public() {}
}
// @matches - '//*[@class="desc docblock-short"]' '^Displayed$'
/// Displayed
#[doc(inline)]
pub use crate::bar as Bar;
// @matches - '//*[@class="desc docblock-short"]' '^Hello\sDisplayed$'
#[doc(inline)]
/// Hello
pub use crate::Bar as Bar2;
// @matches - '//*[@class="desc docblock-short"]' '^Public$'
/// Public
pub use crate::sub::public as Public;

View File

@ -7,10 +7,7 @@ LL | fn oom() -> ! {
| _-^^^^^^^^^^^^
LL | | loop {}
LL | | }
| | -
| | |
| |_unexpected argument of type `core::alloc::Layout`
| help: remove the extra argument
| |_- unexpected argument of type `core::alloc::Layout`
|
note: function defined here
--> $DIR/alloc-error-handler-bad-signature-3.rs:10:4

View File

@ -3,8 +3,15 @@ fn one_arg(_a: i32) {}
fn two_arg_same(_a: i32, _b: i32) {}
fn two_arg_diff(_a: i32, _b: &str) {}
macro_rules! foo {
($x:expr) => {
empty($x, 1); //~ ERROR function takes
}
}
fn main() {
empty(""); //~ ERROR function takes
empty(1, 1); //~ ERROR function takes
one_arg(1, 1); //~ ERROR function takes
one_arg(1, ""); //~ ERROR function takes
@ -32,4 +39,5 @@ fn main() {
1,
""
);
foo!(1);
}

View File

@ -1,5 +1,5 @@
error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/extra_arguments.rs:7:3
--> $DIR/extra_arguments.rs:13:3
|
LL | empty("");
| ^^^^^ --
@ -13,8 +13,27 @@ note: function defined here
LL | fn empty() {}
| ^^^^^
error[E0061]: this function takes 0 arguments but 2 arguments were supplied
--> $DIR/extra_arguments.rs:14:3
|
LL | empty(1, 1);
| ^^^^^ - - unexpected argument of type `{integer}`
| |
| unexpected argument of type `{integer}`
|
note: function defined here
--> $DIR/extra_arguments.rs:1:4
|
LL | fn empty() {}
| ^^^^^
help: remove the extra arguments
|
LL - empty(1, 1);
LL + empty();
|
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/extra_arguments.rs:9:3
--> $DIR/extra_arguments.rs:16:3
|
LL | one_arg(1, 1);
| ^^^^^^^ ---
@ -29,7 +48,7 @@ LL | fn one_arg(_a: i32) {}
| ^^^^^^^ -------
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/extra_arguments.rs:10:3
--> $DIR/extra_arguments.rs:17:3
|
LL | one_arg(1, "");
| ^^^^^^^ ----
@ -44,7 +63,7 @@ LL | fn one_arg(_a: i32) {}
| ^^^^^^^ -------
error[E0061]: this function takes 1 argument but 3 arguments were supplied
--> $DIR/extra_arguments.rs:11:3
--> $DIR/extra_arguments.rs:18:3
|
LL | one_arg(1, "", 1.0);
| ^^^^^^^ -- --- unexpected argument of type `{float}`
@ -63,7 +82,7 @@ LL + one_arg(1);
|
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:13:3
--> $DIR/extra_arguments.rs:20:3
|
LL | two_arg_same(1, 1, 1);
| ^^^^^^^^^^^^ ---
@ -78,7 +97,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:14:3
--> $DIR/extra_arguments.rs:21:3
|
LL | two_arg_same(1, 1, 1.0);
| ^^^^^^^^^^^^ -----
@ -93,7 +112,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:16:3
--> $DIR/extra_arguments.rs:23:3
|
LL | two_arg_diff(1, 1, "");
| ^^^^^^^^^^^^ ---
@ -108,7 +127,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:17:3
--> $DIR/extra_arguments.rs:24:3
|
LL | two_arg_diff(1, "", "");
| ^^^^^^^^^^^^ ----
@ -123,7 +142,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
--> $DIR/extra_arguments.rs:18:3
--> $DIR/extra_arguments.rs:25:3
|
LL | two_arg_diff(1, 1, "", "");
| ^^^^^^^^^^^^ - -- unexpected argument of type `&'static str`
@ -142,7 +161,7 @@ LL + two_arg_diff(1, "");
|
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
--> $DIR/extra_arguments.rs:19:3
--> $DIR/extra_arguments.rs:26:3
|
LL | two_arg_diff(1, "", 1, "");
| ^^^^^^^^^^^^ - -- unexpected argument of type `&'static str`
@ -161,7 +180,7 @@ LL + two_arg_diff(1, "");
|
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:22:3
--> $DIR/extra_arguments.rs:29:3
|
LL | two_arg_same(1, 1, "");
| ^^^^^^^^^^^^ --------
@ -176,7 +195,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:23:3
--> $DIR/extra_arguments.rs:30:3
|
LL | two_arg_diff(1, 1, "");
| ^^^^^^^^^^^^ ---
@ -191,7 +210,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:24:3
--> $DIR/extra_arguments.rs:31:3
|
LL | two_arg_same(
| ^^^^^^^^^^^^
@ -211,7 +230,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:30:3
--> $DIR/extra_arguments.rs:37:3
|
LL | two_arg_diff(
| ^^^^^^^^^^^^
@ -229,6 +248,26 @@ note: function defined here
LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
error: aborting due to 14 previous errors
error[E0061]: this function takes 0 arguments but 2 arguments were supplied
--> $DIR/extra_arguments.rs:8:9
|
LL | empty($x, 1);
| ^^^^^ - unexpected argument of type `{integer}`
...
LL | foo!(1);
| -------
| | |
| | unexpected argument of type `{integer}`
| | help: remove the extra argument
| in this macro invocation
|
note: function defined here
--> $DIR/extra_arguments.rs:1:4
|
LL | fn empty() {}
| ^^^^^
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 16 previous errors
For more information about this error, try `rustc --explain E0061`.

View File

@ -1,5 +1,5 @@
error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
--> $DIR/method-unsatified-assoc-type-predicate.rs:28:7
--> $DIR/method-unsatisfied-assoc-type-predicate.rs:28:7
|
LL | struct S;
| --------
@ -12,7 +12,7 @@ LL | a.f();
| ^ method cannot be called on `S` due to unsatisfied trait bounds
|
note: trait bound `<S as X>::Y<i32> = i32` was not satisfied
--> $DIR/method-unsatified-assoc-type-predicate.rs:12:11
--> $DIR/method-unsatisfied-assoc-type-predicate.rs:12:11
|
LL | impl<T: X<Y<i32> = i32>> M for T {}
| ^^^^^^^^^^^^ - -

View File

@ -1,3 +1,5 @@
#![warn(unused_lifetimes)]
pub trait X {
type Y<'a: 'static>;
//~^ WARNING unnecessary lifetime parameter

View File

@ -1,45 +1,50 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/unsatified-item-lifetime-bound.rs:2:12
--> $DIR/unsatisfied-item-lifetime-bound.rs:4:12
|
LL | type Y<'a: 'static>;
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
note: the lint level is defined here
--> $DIR/unsatisfied-item-lifetime-bound.rs:1:9
|
LL | #![warn(unused_lifetimes)]
| ^^^^^^^^^^^^^^^^
error[E0478]: lifetime bound not satisfied
--> $DIR/unsatified-item-lifetime-bound.rs:11:8
--> $DIR/unsatisfied-item-lifetime-bound.rs:13:8
|
LL | f: <T as X>::Y<'a>,
| ^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
--> $DIR/unsatified-item-lifetime-bound.rs:10:10
--> $DIR/unsatisfied-item-lifetime-bound.rs:12:10
|
LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
| ^^
= note: but lifetime parameter must outlive the static lifetime
error[E0478]: lifetime bound not satisfied
--> $DIR/unsatified-item-lifetime-bound.rs:16:8
--> $DIR/unsatisfied-item-lifetime-bound.rs:18:8
|
LL | f: <T as X>::Y<'a>,
| ^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
--> $DIR/unsatified-item-lifetime-bound.rs:15:10
--> $DIR/unsatisfied-item-lifetime-bound.rs:17:10
|
LL | struct C<'a, T: X> {
| ^^
= note: but lifetime parameter must outlive the static lifetime
error[E0478]: lifetime bound not satisfied
--> $DIR/unsatified-item-lifetime-bound.rs:21:8
--> $DIR/unsatisfied-item-lifetime-bound.rs:23:8
|
LL | f: <() as X>::Y<'a>,
| ^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
--> $DIR/unsatified-item-lifetime-bound.rs:20:10
--> $DIR/unsatisfied-item-lifetime-bound.rs:22:10
|
LL | struct D<'a> {
| ^^

View File

@ -5,7 +5,6 @@
// `'a == 'static` so `&'a i32` is fine as the return type
fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
//~^ WARNING unnecessary lifetime parameter `'a`
x
}

View File

@ -1,10 +0,0 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/equal-hidden-lifetimes.rs:7:25
|
LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: 1 warning emitted

View File

@ -0,0 +1,2 @@
pub struct W<T>(T);
pub type Wrapper<T> = W<T>;

View File

@ -0,0 +1,9 @@
// aux-build: alias.rs
// regression test for 108160
extern crate alias;
use alias::Wrapper;
struct Rec(Wrapper<Rec>); //~ ERROR recursive type `Rec` has infinite
fn main() {}

View File

@ -0,0 +1,14 @@
error[E0072]: recursive type `Rec` has infinite size
--> $DIR/infinite-alias.rs:7:1
|
LL | struct Rec(Wrapper<Rec>);
| ^^^^^^^^^^ ------------ recursive without indirection
|
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | struct Rec(Box<Wrapper<Rec>>);
| ++++ +
error: aborting due to previous error
For more information about this error, try `rustc --explain E0072`.

View File

@ -1,7 +1,7 @@
macro_rules! some_macro {
($other: expr) => ({
($other: expr) => {{
$other(None) //~ NOTE unexpected argument of type `Option<_>`
})
}};
}
fn some_function() {} //~ NOTE defined here
@ -9,5 +9,4 @@ fn some_function() {} //~ NOTE defined here
fn main() {
some_macro!(some_function);
//~^ ERROR function takes 0 arguments but 1 argument was supplied
//~| NOTE in this expansion of some_macro!
}

View File

@ -2,10 +2,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/issue-26094.rs:10:17
|
LL | $other(None)
| ----
| |
| unexpected argument of type `Option<_>`
| help: remove the extra argument
| ---- unexpected argument of type `Option<_>`
...
LL | some_macro!(some_function);
| ^^^^^^^^^^^^^

View File

@ -5,7 +5,6 @@ trait Trait { type Out; }
struct Test<'a> { s: &'a str }
fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
//~^ WARN unnecessary lifetime parameter `'z`
let x = Test { s: "this cannot last" };
&x
//~^ ERROR: cannot return reference to local variable `x`

View File

@ -1,17 +1,9 @@
warning: unnecessary lifetime parameter `'z`
--> $DIR/issue-30438-c.rs:7:74
|
LL | fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'z`
error[E0515]: cannot return reference to local variable `x`
--> $DIR/issue-30438-c.rs:10:5
--> $DIR/issue-30438-c.rs:9:5
|
LL | &x
| ^^ returns a reference to data owned by the current function
error: aborting due to previous error; 1 warning emitted
error: aborting due to previous error
For more information about this error, try `rustc --explain E0515`.

View File

@ -8,6 +8,8 @@
//
// 'a : 'b
#![warn(unused_lifetimes)]
fn test<'a,'b>(x: &'a i32) -> &'b i32
where 'a: 'static //~ WARN unnecessary lifetime parameter `'a`
{

View File

@ -1,10 +1,15 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:12:11
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:14:11
|
LL | where 'a: 'static
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
note: the lint level is defined here
--> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:11:9
|
LL | #![warn(unused_lifetimes)]
| ^^^^^^^^^^^^^^^^
warning: 1 warning emitted

View File

@ -1,5 +1,7 @@
// run-pass
#![warn(unused_lifetimes)]
fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
where 'a: 'static { t }
//~^ WARN unnecessary lifetime parameter `'a`

View File

@ -1,13 +1,18 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound-rpass.rs:4:11
--> $DIR/regions-static-bound-rpass.rs:6:11
|
LL | where 'a: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
note: the lint level is defined here
--> $DIR/regions-static-bound-rpass.rs:3:9
|
LL | #![warn(unused_lifetimes)]
| ^^^^^^^^^^^^^^^^
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound-rpass.rs:8:11
--> $DIR/regions-static-bound-rpass.rs:10:11
|
LL | where 'a: 'static { t }
| ^^
@ -15,7 +20,7 @@ LL | where 'a: 'static { t }
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'b`
--> $DIR/regions-static-bound-rpass.rs:12:19
--> $DIR/regions-static-bound-rpass.rs:14:19
|
LL | where 'a: 'b, 'b: 'static { t }
| ^^

View File

@ -1,6 +1,8 @@
fn static_id<'a,'b>(t: &'a ()) -> &'static ()
where 'a: 'static { t }
//~^ WARN unnecessary lifetime parameter `'a`
#![warn(unused_lifetimes)]
fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
//~^ WARN lifetime parameter `'b` never used
//~| WARN unnecessary lifetime parameter `'a`
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
where 'a: 'b, 'b: 'static { t }

View File

@ -1,13 +1,27 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound.rs:2:11
warning: lifetime parameter `'b` never used
--> $DIR/regions-static-bound.rs:3:17
|
LL | where 'a: 'static { t }
| ^^
LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
| -^^
| |
| help: elide the unused lifetime
|
note: the lint level is defined here
--> $DIR/regions-static-bound.rs:1:9
|
LL | #![warn(unused_lifetimes)]
| ^^^^^^^^^^^^^^^^
warning: unnecessary lifetime parameter `'a`
--> $DIR/regions-static-bound.rs:3:53
|
LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'b`
--> $DIR/regions-static-bound.rs:6:19
--> $DIR/regions-static-bound.rs:8:19
|
LL | where 'a: 'b, 'b: 'static { t }
| ^^
@ -15,7 +29,7 @@ LL | where 'a: 'b, 'b: 'static { t }
= help: you can use the `'static` lifetime directly, in place of `'b`
error: lifetime may not live long enough
--> $DIR/regions-static-bound.rs:10:5
--> $DIR/regions-static-bound.rs:12:5
|
LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
| -- lifetime `'a` defined here
@ -23,7 +37,7 @@ LL | t
| ^ returning this value requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/regions-static-bound.rs:15:5
--> $DIR/regions-static-bound.rs:17:5
|
LL | fn error(u: &(), v: &()) {
| - - let's call the lifetime of this reference `'1`
@ -36,7 +50,7 @@ LL | static_id(&u);
| argument requires that `'1` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/regions-static-bound.rs:17:5
--> $DIR/regions-static-bound.rs:19:5
|
LL | fn error(u: &(), v: &()) {
| - - let's call the lifetime of this reference `'2`
@ -49,6 +63,6 @@ LL | static_id_indirect(&v);
| `v` escapes the function body here
| argument requires that `'2` must outlive `'static`
error: aborting due to 3 previous errors; 2 warnings emitted
error: aborting due to 3 previous errors; 3 warnings emitted
For more information about this error, try `rustc --explain E0521`.

View File

@ -1,4 +1,4 @@
fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a`
fn f<'a: 'static>(_: &'a i32) {}
fn main() {
let x = 0;

View File

@ -1,11 +1,3 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/static-lifetime-bound.rs:1:6
|
LL | fn f<'a: 'static>(_: &'a i32) {}
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
error[E0597]: `x` does not live long enough
--> $DIR/static-lifetime-bound.rs:5:7
|
@ -19,6 +11,6 @@ LL | f(&x);
LL | }
| - `x` dropped here while still borrowed
error: aborting due to previous error; 1 warning emitted
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.

View File

@ -6,7 +6,6 @@
type X<'a> = impl Into<&'static str> + From<&'a str>;
fn f<'a: 'static>(t: &'a str) -> X<'a> {
//~^ WARNING unnecessary lifetime parameter
t
//~^ ERROR expected generic lifetime parameter, found `'static`
}

View File

@ -1,13 +1,5 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/bounds-are-checked.rs:8:6
|
LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
error[E0792]: expected generic lifetime parameter, found `'static`
--> $DIR/bounds-are-checked.rs:10:5
--> $DIR/bounds-are-checked.rs:9:5
|
LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@ -15,6 +7,6 @@ LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
LL | t
| ^
error: aborting due to previous error; 1 warning emitted
error: aborting due to previous error
For more information about this error, try `rustc --explain E0792`.

View File

@ -4,7 +4,6 @@ mod test_lifetime_param {
type Ty<'a> = impl Sized + 'a;
fn defining(a: &str) -> Ty<'_> { a }
fn assert_static<'a: 'static>() {}
//~^ WARN: unnecessary lifetime parameter `'a`
fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}
@ -13,14 +12,12 @@ mod test_higher_kinded_lifetime_param {
type Ty<'a> = impl Sized + 'a;
fn defining(a: &str) -> Ty<'_> { a }
fn assert_static<'a: 'static>() {}
//~^ WARN: unnecessary lifetime parameter `'a`
fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}
mod test_higher_kinded_lifetime_param2 {
fn assert_static<'a: 'static>() {}
//~^ WARN: unnecessary lifetime parameter `'a`
fn test<'a>() { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}

View File

@ -1,41 +1,17 @@
warning: unnecessary lifetime parameter `'a`
--> $DIR/implied_lifetime_wf_check3.rs:6:22
|
LL | fn assert_static<'a: 'static>() {}
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'a`
--> $DIR/implied_lifetime_wf_check3.rs:15:22
|
LL | fn assert_static<'a: 'static>() {}
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'a`
--> $DIR/implied_lifetime_wf_check3.rs:22:22
|
LL | fn assert_static<'a: 'static>() {}
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
error: lifetime may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:8:43
--> $DIR/implied_lifetime_wf_check3.rs:7:43
|
LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:17:46
--> $DIR/implied_lifetime_wf_check3.rs:15:46
|
LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:24:21
--> $DIR/implied_lifetime_wf_check3.rs:21:21
|
LL | fn test<'a>() { assert_static::<'a>() }
| -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
@ -43,7 +19,7 @@ LL | fn test<'a>() { assert_static::<'a>() }
| lifetime `'a` defined here
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:32:41
--> $DIR/implied_lifetime_wf_check3.rs:29:41
|
LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
| ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
@ -53,6 +29,6 @@ help: consider adding an explicit lifetime bound...
LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() }
| +++++++++
error: aborting due to 4 previous errors; 3 warnings emitted
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0310`.