Auto merge of #109581 - matthiaskrgr:rollup-e8fi2vi, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #109355 (Fix bad suggestion for clone/is_some in field init shorthand) - #109484 (Bugfix: avoid panic on invalid json output from libtest) - #109539 (Refactor `find_*_stability` functions) - #109542 (rustdoc: clean up `storage.js`) - #109545 (Deeply check well-formedness of return-position `impl Trait` in trait) - #109568 (miri: fix raw pointer dyn receivers) - #109570 (Add GUI test for "Auto-hide item methods' documentation" setting) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
96bd50dd47
18 changed files with 633 additions and 448 deletions
|
@ -226,315 +226,39 @@ impl UnstableReason {
|
|||
}
|
||||
}
|
||||
|
||||
/// Collects stability info from all stability attributes in `attrs`.
|
||||
/// Returns `None` if no stability attributes are found.
|
||||
/// Collects stability info from `stable`/`unstable`/`rustc_allowed_through_unstable_modules`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
pub fn find_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
item_sp: Span,
|
||||
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
|
||||
{
|
||||
find_stability_generic(sess, attrs.iter(), item_sp)
|
||||
}
|
||||
|
||||
fn find_stability_generic<'a, I>(
|
||||
sess: &Session,
|
||||
attrs_iter: I,
|
||||
item_sp: Span,
|
||||
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
|
||||
where
|
||||
I: Iterator<Item = &'a Attribute>,
|
||||
{
|
||||
use StabilityLevel::*;
|
||||
|
||||
) -> Option<(Stability, Span)> {
|
||||
let mut stab: Option<(Stability, Span)> = None;
|
||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
|
||||
let mut promotable = false;
|
||||
let mut allowed_through_unstable_modules = false;
|
||||
|
||||
'outer: for attr in attrs_iter {
|
||||
if ![
|
||||
sym::rustc_const_unstable,
|
||||
sym::rustc_const_stable,
|
||||
sym::unstable,
|
||||
sym::stable,
|
||||
sym::rustc_promotable,
|
||||
sym::rustc_allowed_through_unstable_modules,
|
||||
sym::rustc_default_body_unstable,
|
||||
]
|
||||
.iter()
|
||||
.any(|&s| attr.has_name(s))
|
||||
{
|
||||
continue; // not a stability level
|
||||
}
|
||||
|
||||
let meta = attr.meta();
|
||||
|
||||
if attr.has_name(sym::rustc_promotable) {
|
||||
promotable = true;
|
||||
} else if attr.has_name(sym::rustc_allowed_through_unstable_modules) {
|
||||
allowed_through_unstable_modules = true;
|
||||
}
|
||||
// attributes with data
|
||||
else if let Some(meta @ MetaItem { kind: MetaItemKind::List(metas), .. }) = &meta {
|
||||
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false;
|
||||
for attr in attrs {
|
||||
match attr.name_or_empty() {
|
||||
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
|
||||
sym::unstable => {
|
||||
if stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
true
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
false
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
}
|
||||
};
|
||||
|
||||
let meta_name = meta.name_or_empty();
|
||||
match meta_name {
|
||||
sym::rustc_const_unstable | sym::rustc_default_body_unstable | sym::unstable => {
|
||||
if meta_name == sym::unstable && stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
} else if meta_name == sym::rustc_const_unstable && const_stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
} else if meta_name == sym::rustc_default_body_unstable && body_stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
let mut feature = None;
|
||||
let mut reason = None;
|
||||
let mut issue = None;
|
||||
let mut issue_num = None;
|
||||
let mut is_soft = false;
|
||||
let mut implied_by = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
|
||||
);
|
||||
continue 'outer;
|
||||
};
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !get(mi, &mut feature) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::reason => {
|
||||
if !get(mi, &mut reason) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::issue => {
|
||||
if !get(mi, &mut issue) {
|
||||
continue 'outer;
|
||||
}
|
||||
|
||||
// These unwraps are safe because `get` ensures the meta item
|
||||
// is a name/value pair string literal.
|
||||
issue_num = match issue.unwrap().as_str() {
|
||||
"none" => None,
|
||||
issue => match issue.parse::<NonZeroU32>() {
|
||||
Ok(num) => Some(num),
|
||||
Err(err) => {
|
||||
sess.emit_err(
|
||||
session_diagnostics::InvalidIssueString {
|
||||
span: mi.span,
|
||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||
mi.name_value_literal_span().unwrap(),
|
||||
err.kind(),
|
||||
),
|
||||
},
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
sym::soft => {
|
||||
if !mi.is_word() {
|
||||
sess.emit_err(session_diagnostics::SoftNoArgs {
|
||||
span: mi.span,
|
||||
});
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
sym::implied_by => {
|
||||
if !get(mi, &mut implied_by) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "reason", "issue", "soft"],
|
||||
),
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match (feature, reason, issue) {
|
||||
(Some(feature), reason, Some(_)) => {
|
||||
if !rustc_lexer::is_ident(feature.as_str()) {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::NonIdentFeature,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
let level = Unstable {
|
||||
reason: UnstableReason::from_opt_reason(reason),
|
||||
issue: issue_num,
|
||||
is_soft,
|
||||
implied_by,
|
||||
};
|
||||
if sym::unstable == meta_name {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
} else if sym::rustc_const_unstable == meta_name {
|
||||
const_stab = Some((
|
||||
ConstStability { level, feature, promotable: false },
|
||||
attr.span,
|
||||
));
|
||||
} else if sym::rustc_default_body_unstable == meta_name {
|
||||
body_stab =
|
||||
Some((DefaultBodyStability { level, feature }, attr.span));
|
||||
} else {
|
||||
unreachable!("Unknown stability attribute {meta_name}");
|
||||
}
|
||||
}
|
||||
(None, _, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
sess.emit_err(session_diagnostics::MissingIssue { span: attr.span });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
sym::rustc_const_stable | sym::stable => {
|
||||
if meta_name == sym::stable && stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
} else if meta_name == sym::rustc_const_stable && const_stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
let mut feature = None;
|
||||
let mut since = None;
|
||||
for meta in metas {
|
||||
match meta {
|
||||
NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !get(mi, &mut feature) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::since => {
|
||||
if !get(mi, &mut since) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "since"],
|
||||
),
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
},
|
||||
NestedMetaItem::Lit(lit) => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
lit.span,
|
||||
AttrError::UnsupportedLiteral(
|
||||
UnsupportedLiteralReason::Generic,
|
||||
false,
|
||||
),
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
|
||||
since = Some(rust_version_symbol());
|
||||
}
|
||||
|
||||
match (feature, since) {
|
||||
(Some(feature), Some(since)) => {
|
||||
let level = Stable { since, allowed_through_unstable_modules: false };
|
||||
if sym::stable == meta_name {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
} else {
|
||||
const_stab = Some((
|
||||
ConstStability { level, feature, promotable: false },
|
||||
attr.span,
|
||||
));
|
||||
}
|
||||
}
|
||||
(None, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => stab.promotable = promotable,
|
||||
_ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
|
||||
sym::stable => {
|
||||
if stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,7 +277,286 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
(stab, const_stab, body_stab)
|
||||
stab
|
||||
}
|
||||
|
||||
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
pub fn find_const_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
item_sp: Span,
|
||||
) -> Option<(ConstStability, Span)> {
|
||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||
let mut promotable = false;
|
||||
|
||||
for attr in attrs {
|
||||
match attr.name_or_empty() {
|
||||
sym::rustc_promotable => promotable = true,
|
||||
sym::rustc_const_unstable => {
|
||||
if const_stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
const_stab =
|
||||
Some((ConstStability { level, feature, promotable: false }, attr.span));
|
||||
}
|
||||
}
|
||||
sym::rustc_const_stable => {
|
||||
if const_stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||
const_stab =
|
||||
Some((ConstStability { level, feature, promotable: false }, attr.span));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => stab.promotable = promotable,
|
||||
_ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
|
||||
}
|
||||
}
|
||||
|
||||
const_stab
|
||||
}
|
||||
|
||||
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
|
||||
/// Returns `None` if no stability attributes are found.
|
||||
pub fn find_body_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
) -> Option<(DefaultBodyStability, Span)> {
|
||||
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
|
||||
|
||||
for attr in attrs {
|
||||
if attr.has_name(sym::rustc_default_body_unstable) {
|
||||
if body_stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
body_stab = Some((DefaultBodyStability { level, feature }, attr.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body_stab
|
||||
}
|
||||
|
||||
/// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and
|
||||
/// its stability information.
|
||||
fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
|
||||
let meta = attr.meta()?;
|
||||
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
|
||||
let insert_or_error = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
true
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let mut feature = None;
|
||||
let mut since = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !insert_or_error(mi, &mut feature) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
sym::since => {
|
||||
if !insert_or_error(mi, &mut since) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "since"],
|
||||
),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
|
||||
since = Some(rust_version_symbol());
|
||||
}
|
||||
|
||||
match (feature, since) {
|
||||
(Some(feature), Some(since)) => {
|
||||
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
|
||||
Some((feature, level))
|
||||
}
|
||||
(None, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
|
||||
/// attribute, and return the feature name and its stability information.
|
||||
fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
|
||||
let meta = attr.meta()?;
|
||||
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
|
||||
let insert_or_error = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
true
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let mut feature = None;
|
||||
let mut reason = None;
|
||||
let mut issue = None;
|
||||
let mut issue_num = None;
|
||||
let mut is_soft = false;
|
||||
let mut implied_by = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !insert_or_error(mi, &mut feature) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
sym::reason => {
|
||||
if !insert_or_error(mi, &mut reason) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
sym::issue => {
|
||||
if !insert_or_error(mi, &mut issue) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// These unwraps are safe because `insert_or_error` ensures the meta item
|
||||
// is a name/value pair string literal.
|
||||
issue_num = match issue.unwrap().as_str() {
|
||||
"none" => None,
|
||||
issue => match issue.parse::<NonZeroU32>() {
|
||||
Ok(num) => Some(num),
|
||||
Err(err) => {
|
||||
sess.emit_err(
|
||||
session_diagnostics::InvalidIssueString {
|
||||
span: mi.span,
|
||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||
mi.name_value_literal_span().unwrap(),
|
||||
err.kind(),
|
||||
),
|
||||
},
|
||||
);
|
||||
return None;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
sym::soft => {
|
||||
if !mi.is_word() {
|
||||
sess.emit_err(session_diagnostics::SoftNoArgs { span: mi.span });
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
sym::implied_by => {
|
||||
if !insert_or_error(mi, &mut implied_by) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "reason", "issue", "soft", "implied_by"],
|
||||
),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match (feature, reason, issue) {
|
||||
(Some(feature), reason, Some(_)) => {
|
||||
if !rustc_lexer::is_ident(feature.as_str()) {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::NonIdentFeature);
|
||||
return None;
|
||||
}
|
||||
let level = StabilityLevel::Unstable {
|
||||
reason: UnstableReason::from_opt_reason(reason),
|
||||
issue: issue_num,
|
||||
is_soft,
|
||||
implied_by,
|
||||
};
|
||||
Some((feature, level))
|
||||
}
|
||||
(None, _, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
return None;
|
||||
}
|
||||
_ => {
|
||||
sess.emit_err(session_diagnostics::MissingIssue { span: attr.span });
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
|
||||
|
|
|
@ -539,7 +539,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let mut receiver = args[0].clone();
|
||||
let receiver_place = loop {
|
||||
match receiver.layout.ty.kind() {
|
||||
ty::Ref(..) | ty::RawPtr(..) => break self.deref_operand(&receiver)?,
|
||||
ty::Ref(..) | ty::RawPtr(..) => {
|
||||
// We do *not* use `deref_operand` here: we don't want to conceptually
|
||||
// create a place that must be dereferenceable, since the receiver might
|
||||
// be a raw pointer and (for `*const dyn Trait`) we don't need to
|
||||
// actually access memory to resolve this method.
|
||||
// Also see <https://github.com/rust-lang/miri/issues/2786>.
|
||||
let val = self.read_immediate(&receiver)?;
|
||||
break self.ref_to_mplace(&val)?;
|
||||
}
|
||||
ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
|
||||
ty::Dynamic(.., ty::DynStar) => {
|
||||
// Not clear how to handle this, so far we assume the receiver is always a pointer.
|
||||
|
|
|
@ -793,7 +793,9 @@ impl SyntaxExtension {
|
|||
)
|
||||
})
|
||||
.unwrap_or_else(|| (None, helper_attrs));
|
||||
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
|
||||
let stability = attr::find_stability(&sess, attrs, span);
|
||||
let const_stability = attr::find_const_stability(&sess, attrs, span);
|
||||
let body_stability = attr::find_body_stability(&sess, attrs);
|
||||
if let Some((_, sp)) = const_stability {
|
||||
sess.emit_err(errors::MacroConstStability {
|
||||
span: sp,
|
||||
|
|
|
@ -1544,42 +1544,81 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
|
|||
span: Span,
|
||||
) {
|
||||
let tcx = wfcx.tcx();
|
||||
if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
|
||||
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
|
||||
{
|
||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
|
||||
// strategy, we can't just call `check_associated_item` on the new RPITITs,
|
||||
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
|
||||
// That's because we need to check that the bounds of the RPITIT hold using
|
||||
// the special substs that we create during opaque type lowering, otherwise we're
|
||||
// getting a bunch of early bound and free regions mixed up... Haven't looked too
|
||||
// deep into this, though.
|
||||
for arg in fn_output.walk() {
|
||||
if let ty::GenericArgKind::Type(ty) = arg.unpack()
|
||||
// RPITITs are always eagerly normalized into opaques, so always look for an
|
||||
// opaque here.
|
||||
&& let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
|
||||
&& let Some(opaque_def_id) = opaque_ty.def_id.as_local()
|
||||
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
|
||||
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
|
||||
&& source == fn_def_id
|
||||
let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
|
||||
return;
|
||||
};
|
||||
if assoc_item.container != ty::AssocItemContainer::TraitContainer {
|
||||
return;
|
||||
}
|
||||
fn_output.visit_with(&mut ImplTraitInTraitFinder {
|
||||
wfcx,
|
||||
fn_def_id,
|
||||
depth: ty::INNERMOST,
|
||||
seen: FxHashSet::default(),
|
||||
});
|
||||
}
|
||||
|
||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
|
||||
// strategy, we can't just call `check_associated_item` on the new RPITITs,
|
||||
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
|
||||
// That's because we need to check that the bounds of the RPITIT hold using
|
||||
// the special substs that we create during opaque type lowering, otherwise we're
|
||||
// getting a bunch of early bound and free regions mixed up... Haven't looked too
|
||||
// deep into this, though.
|
||||
struct ImplTraitInTraitFinder<'a, 'tcx> {
|
||||
wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
|
||||
fn_def_id: LocalDefId,
|
||||
depth: ty::DebruijnIndex,
|
||||
seen: FxHashSet<DefId>,
|
||||
}
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
|
||||
type BreakTy = !;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
|
||||
let tcx = self.wfcx.tcx();
|
||||
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
|
||||
&& self.seen.insert(unshifted_opaque_ty.def_id)
|
||||
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
|
||||
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
|
||||
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
|
||||
&& source == self.fn_def_id
|
||||
{
|
||||
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| {
|
||||
if let ty::ReLateBound(index, bv) = re.kind() {
|
||||
if depth != ty::INNERMOST {
|
||||
return tcx.mk_re_error_with_message(
|
||||
DUMMY_SP,
|
||||
"we shouldn't walk non-predicate binders with `impl Trait`...",
|
||||
);
|
||||
}
|
||||
tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
|
||||
} else {
|
||||
re
|
||||
}
|
||||
});
|
||||
for (bound, bound_span) in tcx
|
||||
.bound_explicit_item_bounds(opaque_ty.def_id)
|
||||
.subst_iter_copied(tcx, opaque_ty.substs)
|
||||
{
|
||||
let span = tcx.def_span(opaque_ty.def_id);
|
||||
let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
|
||||
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
|
||||
let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
|
||||
let normalized_bound = wfcx.normalize(span, None, bound);
|
||||
traits::wf::predicate_obligations(
|
||||
wfcx.infcx,
|
||||
wfcx.param_env,
|
||||
wfcx.body_def_id,
|
||||
normalized_bound,
|
||||
bound_span,
|
||||
)
|
||||
});
|
||||
wfcx.register_obligations(wf_obligations);
|
||||
let bound = self.wfcx.normalize(bound_span, None, bound);
|
||||
self.wfcx.register_obligations(traits::wf::predicate_obligations(
|
||||
self.wfcx.infcx,
|
||||
self.wfcx.param_env,
|
||||
self.wfcx.body_def_id,
|
||||
bound,
|
||||
bound_span,
|
||||
));
|
||||
// Set the debruijn index back to innermost here, since we already eagerly
|
||||
// shifted the substs that we use to generate these bounds. This is unfortunately
|
||||
// subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
|
||||
// but that function doesn't actually need to normalize the bound it's visiting
|
||||
// (whereas we have to do so here)...
|
||||
let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
|
||||
bound.visit_with(self);
|
||||
self.depth = old_depth;
|
||||
}
|
||||
}
|
||||
ty.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -983,13 +983,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
".clone()",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
Some(ident) => format!(": {}.clone()", ident),
|
||||
None => ".clone()".to_string()
|
||||
};
|
||||
|
||||
diag.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -1150,13 +1155,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
|
||||
diag.span_suggestion(
|
||||
let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
Some(ident) => format!(": {}.is_some()", ident),
|
||||
None => ".is_some()".to_string(),
|
||||
};
|
||||
|
||||
diag.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
"use `Option::is_some` to test if the `Option` has a value",
|
||||
".is_some()",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -159,7 +159,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let (stab, const_stab, body_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
|
||||
let stab = attr::find_stability(&self.tcx.sess, attrs, item_sp);
|
||||
let const_stab = attr::find_const_stability(&self.tcx.sess, attrs, item_sp);
|
||||
let body_stab = attr::find_body_stability(&self.tcx.sess, attrs);
|
||||
let mut const_span = None;
|
||||
|
||||
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
|
||||
|
@ -742,8 +744,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||
let features = self.tcx.features();
|
||||
if features.staged_api {
|
||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
||||
let (stab, const_stab, _) =
|
||||
attr::find_stability(&self.tcx.sess, attrs, item.span);
|
||||
let stab = attr::find_stability(&self.tcx.sess, attrs, item.span);
|
||||
let const_stab = attr::find_const_stability(&self.tcx.sess, attrs, item.span);
|
||||
|
||||
// If this impl block has an #[unstable] attribute, give an
|
||||
// error if all involved types and traits are stable, because
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue