Auto merge of #122735 - matthiaskrgr:rollup-pgb1s90, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #122435 (Don't trigger `unused_qualifications` on global paths)
 - #122556 (Extend format arg help for simple tuple index access expression)
 - #122634 (compiletest: Add support for `//@ aux-bin: foo.rs`)
 - #122677 (Fix incorrect mutable suggestion information for binding in ref pattern.)
 - #122691 (Fix ICE: `global_asm!()` Don't Panic When Unable to Evaluate Constant)
 - #122695 (Change only_local to a enum type.)
 - #122717 (Ensure stack before parsing dot-or-call)
 - #122719 (Ensure nested statics have a HIR node to prevent various queries from ICEing)
 - #122720 ([doc]:fix error code example)
 - #122724 (add test for casting pointer to union with unsized tail)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-03-19 17:52:46 +00:00
commit e760daa6a7
45 changed files with 5599 additions and 369 deletions

View File

@ -55,7 +55,7 @@ pub(super) fn index_hir<'hir>(
OwnerNode::TraitItem(item) => collector.visit_trait_item(item),
OwnerNode::ImplItem(item) => collector.visit_impl_item(item),
OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item),
OwnerNode::AssocOpaqueTy(..) => unreachable!(),
OwnerNode::Synthetic => unreachable!(),
};
for (local_id, node) in collector.nodes.iter_enumerated() {

View File

@ -2,7 +2,7 @@
#![allow(rustc::untranslatable_diagnostic)]
use core::ops::ControlFlow;
use hir::ExprKind;
use hir::{ExprKind, Param};
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
@ -725,25 +725,26 @@ fn construct_mut_suggestion_for_local_binding_patterns(
_ => local_decl.source_info.span,
};
let def_id = self.body.source.def_id();
let hir_id = if let Some(local_def_id) = def_id.as_local()
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
{
let body = self.infcx.tcx.hir().body(body_id);
BindingFinder { span: pat_span }.visit_body(body).break_value()
} else {
None
};
// With ref-binding patterns, the mutability suggestion has to apply to
// the binding, not the reference (which would be a type error):
//
// `let &b = a;` -> `let &(mut b) = a;`
if let Some(hir_id) = hir_id
// or
// `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)`
let def_id = self.body.source.def_id();
if let Some(local_def_id) = def_id.as_local()
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
&& let body = self.infcx.tcx.hir().body(body_id)
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(body).break_value()
&& let node = self.infcx.tcx.hir_node(hir_id)
&& let hir::Node::Local(hir::Local {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
..
}) = self.infcx.tcx.hir_node(hir_id)
})
| hir::Node::Param(Param {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
..
}) = node
&& let Ok(name) =
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
{
@ -1310,6 +1311,16 @@ fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result {
hir::intravisit::walk_stmt(self, s)
}
}
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result {
if let hir::Pat { kind: hir::PatKind::Ref(_, _), span, .. } = param.pat
&& *span == self.span
{
ControlFlow::Break(param.hir_id)
} else {
ControlFlow::Continue(())
}
}
}
pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {

View File

@ -2,6 +2,7 @@
use crate::common;
use crate::traits::*;
use rustc_hir as hir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty;
@ -40,23 +41,34 @@ fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
.iter()
.map(|(op, op_sp)| match *op {
hir::InlineAsmOperand::Const { ref anon_const } => {
let const_value = cx
.tcx()
.const_eval_poly(anon_const.def_id.to_def_id())
.unwrap_or_else(|_| {
span_bug!(*op_sp, "asm const cannot be resolved")
});
let ty = cx
.tcx()
.typeck_body(anon_const.body)
.node_type(anon_const.hir_id);
let string = common::asm_const_to_str(
cx.tcx(),
*op_sp,
const_value,
cx.layout_of(ty),
);
GlobalAsmOperandRef::Const { string }
match cx.tcx().const_eval_poly(anon_const.def_id.to_def_id()) {
Ok(const_value) => {
let ty = cx
.tcx()
.typeck_body(anon_const.body)
.node_type(anon_const.hir_id);
let string = common::asm_const_to_str(
cx.tcx(),
*op_sp,
const_value,
cx.layout_of(ty),
);
GlobalAsmOperandRef::Const { string }
}
Err(ErrorHandled::Reported { .. }) => {
// An error has already been reported and
// compilation is guaranteed to fail if execution
// hits this path. So an empty string instead of
// a stringified constant value will suffice.
GlobalAsmOperandRef::Const { string: String::new() }
}
Err(ErrorHandled::TooGeneric(_)) => {
span_bug!(
*op_sp,
"asm const cannot be resolved; too generic"
)
}
}
}
hir::InlineAsmOperand::SymFn { ref anon_const } => {
let ty = cx

View File

@ -111,6 +111,8 @@ fn intern_as_new_static<'tcx>(
feed.generics_of(tcx.generics_of(static_id).clone());
feed.def_ident_span(tcx.def_ident_span(static_id));
feed.explicit_predicates_of(tcx.explicit_predicates_of(static_id));
feed.feed_hir()
}
/// How a constant value should be interned.

File diff suppressed because it is too large Load Diff

View File

@ -124,7 +124,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
pub use accepted::ACCEPTED_FEATURES;
pub use builtin_attrs::AttributeDuplicates;
pub use builtin_attrs::{
deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local,
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute,
GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
};

View File

@ -2552,11 +2552,6 @@ pub struct OpaqueTy<'hir> {
pub in_trait: bool,
}
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub struct AssocOpaqueTy {
// Add some data if necessary
}
/// From whence the opaque type came.
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
pub enum OpaqueTyOrigin {
@ -3367,7 +3362,7 @@ pub enum OwnerNode<'hir> {
TraitItem(&'hir TraitItem<'hir>),
ImplItem(&'hir ImplItem<'hir>),
Crate(&'hir Mod<'hir>),
AssocOpaqueTy(&'hir AssocOpaqueTy),
Synthetic,
}
impl<'hir> OwnerNode<'hir> {
@ -3377,7 +3372,7 @@ pub fn ident(&self) -> Option<Ident> {
| OwnerNode::ForeignItem(ForeignItem { ident, .. })
| OwnerNode::ImplItem(ImplItem { ident, .. })
| OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident),
OwnerNode::Crate(..) | OwnerNode::AssocOpaqueTy(..) => None,
OwnerNode::Crate(..) | OwnerNode::Synthetic => None,
}
}
@ -3390,7 +3385,7 @@ pub fn span(&self) -> &'hir Span {
| OwnerNode::ImplItem(ImplItem { span, .. })
| OwnerNode::TraitItem(TraitItem { span, .. }) => span,
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span,
OwnerNode::AssocOpaqueTy(..) => unreachable!(),
OwnerNode::Synthetic => unreachable!(),
}
}
@ -3449,7 +3444,7 @@ pub fn def_id(self) -> OwnerId {
| OwnerNode::ImplItem(ImplItem { owner_id, .. })
| OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id,
OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
OwnerNode::AssocOpaqueTy(..) => unreachable!(),
OwnerNode::Synthetic => unreachable!(),
}
}
@ -3493,7 +3488,7 @@ fn into(self) -> Node<'hir> {
OwnerNode::ImplItem(n) => Node::ImplItem(n),
OwnerNode::TraitItem(n) => Node::TraitItem(n),
OwnerNode::Crate(n) => Node::Crate(n),
OwnerNode::AssocOpaqueTy(n) => Node::AssocOpaqueTy(n),
OwnerNode::Synthetic => Node::Synthetic,
}
}
}
@ -3531,7 +3526,8 @@ pub enum Node<'hir> {
WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>),
// FIXME: Merge into `Node::Infer`.
ArrayLenInfer(&'hir InferArg),
AssocOpaqueTy(&'hir AssocOpaqueTy),
// Created by query feeding
Synthetic,
// Span by reference to minimize `Node`'s size
#[allow(rustc::pass_by_value)]
Err(&'hir Span),
@ -3582,7 +3578,7 @@ pub fn ident(&self) -> Option<Ident> {
| Node::Infer(..)
| Node::WhereBoundPredicate(..)
| Node::ArrayLenInfer(..)
| Node::AssocOpaqueTy(..)
| Node::Synthetic
| Node::Err(..) => None,
}
}
@ -3695,7 +3691,7 @@ pub fn as_owner(self) -> Option<OwnerNode<'hir>> {
Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
Node::Crate(i) => Some(OwnerNode::Crate(i)),
Node::AssocOpaqueTy(i) => Some(OwnerNode::AssocOpaqueTy(i)),
Node::Synthetic => Some(OwnerNode::Synthetic),
_ => None,
}
}

View File

@ -196,7 +196,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorG
hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
hir::OwnerNode::Synthetic => unreachable!(),
};
if let Some(generics) = node.generics() {

View File

@ -262,7 +262,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
visitor.visit_impl_item(item)
}
hir::OwnerNode::Crate(_) => {}
hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
hir::OwnerNode::Synthetic => unreachable!(),
}
let mut rl = ResolveBoundVars::default();

View File

@ -121,7 +121,7 @@ fn print_node(&mut self, node: Node<'_>) {
self.print_bounds(":", pred.bounds);
}
Node::ArrayLenInfer(_) => self.word("_"),
Node::AssocOpaqueTy(..) => unreachable!(),
Node::Synthetic => unreachable!(),
Node::Err(_) => self.word("/*ERROR*/"),
}
}

View File

@ -2553,7 +2553,7 @@ fn visit_ty(&mut self, ty: &'hir hir::Ty<'hir>) {
hir::OwnerNode::ImplItem(i) => visitor.visit_impl_item(i),
hir::OwnerNode::TraitItem(i) => visitor.visit_trait_item(i),
hir::OwnerNode::Crate(_) => bug!("OwnerNode::Crate doesn't not have generics"),
hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
hir::OwnerNode::Synthetic => unreachable!(),
}
let ast_generics = self.tcx.hir().get_generics(lifetime_scope).unwrap();

View File

@ -191,7 +191,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe
levels.add_id(hir::CRATE_HIR_ID);
levels.visit_mod(mod_, mod_.spans.inner_span, hir::CRATE_HIR_ID)
}
hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
hir::OwnerNode::Synthetic => unreachable!(),
},
}

View File

@ -817,8 +817,8 @@ struct AnalyzeAttrState {
#[inline]
fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
let mut should_encode = false;
if rustc_feature::is_builtin_only_local(attr.name_or_empty()) {
// Attributes marked local-only don't need to be encoded for downstream crates.
if !rustc_feature::encode_cross_crate(attr.name_or_empty()) {
// Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
} else if attr.doc_str().is_some() {
// We keep all doc comments reachable to rustdoc because they might be "imported" into
// downstream crates if they use `#[doc(inline)]` to copy an item's documentation into

View File

@ -914,7 +914,7 @@ pub fn span_with_body(self, hir_id: HirId) -> Span {
Node::Crate(item) => item.spans.inner_span,
Node::WhereBoundPredicate(pred) => pred.span,
Node::ArrayLenInfer(inf) => inf.span,
Node::AssocOpaqueTy(..) => unreachable!(),
Node::Synthetic => unreachable!(),
Node::Err(span) => *span,
}
}
@ -1179,7 +1179,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
Node::Crate(..) => String::from("(root_crate)"),
Node::WhereBoundPredicate(_) => node_str("where bound predicate"),
Node::ArrayLenInfer(_) => node_str("array len infer"),
Node::AssocOpaqueTy(..) => unreachable!(),
Node::Synthetic => unreachable!(),
Node::Err(_) => node_str("error"),
}
}

View File

@ -596,6 +596,27 @@ pub fn def_id(&self) -> LocalDefId {
pub fn feed_owner_id(&self) -> TyCtxtFeed<'tcx, hir::OwnerId> {
TyCtxtFeed { tcx: self.tcx, key: hir::OwnerId { def_id: self.key } }
}
// Fills in all the important parts needed by HIR queries
pub fn feed_hir(&self) {
self.local_def_id_to_hir_id(HirId::make_owner(self.def_id()));
let node = hir::OwnerNode::Synthetic;
let bodies = Default::default();
let attrs = hir::AttributeMap::EMPTY;
let (opt_hash_including_bodies, _) = self.tcx.hash_owner_nodes(node, &bodies, &attrs.map);
let node = node.into();
self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes {
opt_hash_including_bodies,
nodes: IndexVec::from_elem_n(
hir::ParentedNode { parent: hir::ItemLocalId::INVALID, node },
1,
),
bodies,
})));
self.feed_owner_id().hir_attrs(attrs);
}
}
/// The central data structure of the compiler. It stores references

View File

@ -1752,9 +1752,8 @@ pub fn get_attrs(
let filter_fn = move |a: &&ast::Attribute| a.has_name(attr);
if let Some(did) = did.as_local() {
self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) {
bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr);
} else {
debug_assert!(rustc_feature::encode_cross_crate(attr));
self.item_attrs(did).iter().filter(filter_fn)
}
}
@ -1786,12 +1785,7 @@ pub fn get_attr(self, did: impl Into<DefId>, attr: Symbol) -> Option<&'tcx ast::
/// Determines whether an item is annotated with an attribute.
pub fn has_attr(self, did: impl Into<DefId>, attr: Symbol) -> bool {
let did: DefId = did.into();
if cfg!(debug_assertions) && !did.is_local() && rustc_feature::is_builtin_only_local(attr) {
bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr);
} else {
self.get_attrs(did, attr).next().is_some()
}
self.get_attrs(did, attr).next().is_some()
}
/// Returns `true` if this is an `auto trait`.

View File

@ -943,7 +943,10 @@ pub(super) fn parse_expr_dot_or_call_with(
// Stitch the list of outer attributes onto the return value.
// A little bit ugly, but the best way given the current code
// structure
let res = self.parse_expr_dot_or_call_with_(e0, lo);
let res = ensure_sufficient_stack(
// this expr demonstrates the recursion it guards against
|| self.parse_expr_dot_or_call_with_(e0, lo),
);
if attrs.is_empty() {
res
} else {

View File

@ -907,25 +907,47 @@ fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>)
let byte_pos = self.to_span_index(end);
let start = InnerOffset(byte_pos.0 + 1);
let field = self.argument(start);
// We can only parse `foo.bar` field access, any deeper nesting,
// or another type of expression, like method calls, are not supported
// We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any
// deeper nesting, or another type of expression, like method calls, are not supported
if !self.consume('}') {
return;
}
if let ArgumentNamed(_) = arg.position {
if let ArgumentNamed(_) = field.position {
self.errors.insert(
0,
ParseError {
description: "field access isn't supported".to_string(),
note: None,
label: "not supported".to_string(),
span: InnerSpan::new(arg.position_span.start, field.position_span.end),
secondary_label: None,
suggestion: Suggestion::UsePositional,
},
);
}
match field.position {
ArgumentNamed(_) => {
self.errors.insert(
0,
ParseError {
description: "field access isn't supported".to_string(),
note: None,
label: "not supported".to_string(),
span: InnerSpan::new(
arg.position_span.start,
field.position_span.end,
),
secondary_label: None,
suggestion: Suggestion::UsePositional,
},
);
}
ArgumentIs(_) => {
self.errors.insert(
0,
ParseError {
description: "tuple index access isn't supported".to_string(),
note: None,
label: "not supported".to_string(),
span: InnerSpan::new(
arg.position_span.start,
field.position_span.end,
),
secondary_label: None,
suggestion: Suggestion::UsePositional,
},
);
}
_ => {}
};
}
}
}

View File

@ -247,7 +247,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
| Node::Field(_)
| Node::Ty(_)
| Node::Crate(_)
| Node::AssocOpaqueTy(..) => {}
| Node::Synthetic => {}
_ => {
bug!(
"found unexpected node kind in worklist: {} ({:?})",

View File

@ -4665,6 +4665,13 @@ fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExport
}
fn lint_unused_qualifications(&mut self, path: &[Segment], ns: Namespace, finalize: Finalize) {
// Don't lint on global paths because the user explicitly wrote out the full path.
if let Some(seg) = path.first()
&& seg.ident.name == kw::PathRoot
{
return;
}
if path.iter().any(|seg| seg.ident.span.from_expansion()) {
return;
}

View File

@ -1,11 +1,10 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, HirId};
use rustc_index::IndexVec;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt, TyCtxtFeed};
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
use rustc_span::symbol::kw;
pub(crate) fn provide(providers: &mut Providers) {
@ -238,28 +237,6 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
}
}
fn feed_hir(feed: &TyCtxtFeed<'_, LocalDefId>) {
feed.local_def_id_to_hir_id(HirId::make_owner(feed.def_id()));
let node = hir::OwnerNode::AssocOpaqueTy(&hir::AssocOpaqueTy {});
let bodies = Default::default();
let attrs = hir::AttributeMap::EMPTY;
let (opt_hash_including_bodies, _) = feed.tcx.hash_owner_nodes(node, &bodies, &attrs.map);
feed.opt_hir_owner_nodes(Some(feed.tcx.arena.alloc(hir::OwnerNodes {
opt_hash_including_bodies,
nodes: IndexVec::from_elem_n(
hir::ParentedNode {
parent: hir::ItemLocalId::INVALID,
node: hir::Node::AssocOpaqueTy(&hir::AssocOpaqueTy {}),
},
1,
),
bodies,
})));
feed.feed_owner_id().hir_attrs(attrs);
}
/// Given an `opaque_ty_def_id` corresponding to an `impl Trait` in an associated
/// function from a trait, synthesize an associated type for that `impl Trait`
/// that inherits properties that we infer from the method and the opaque type.
@ -281,7 +258,7 @@ fn associated_type_for_impl_trait_in_trait(
let local_def_id = trait_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
feed_hir(&trait_assoc_ty);
trait_assoc_ty.feed_hir();
// Copy span of the opaque.
trait_assoc_ty.def_ident_span(Some(span));
@ -335,7 +312,7 @@ fn associated_type_for_impl_trait_in_impl(
let local_def_id = impl_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
feed_hir(&impl_assoc_ty);
impl_assoc_ty.feed_hir();
// Copy span of the opaque.
impl_assoc_ty.def_ident_span(Some(span));

View File

@ -1337,7 +1337,7 @@ impl<T> SizedTypeProperties for T {}
/// type B = Wrapper<u8, i8>;
///
/// // Not necessarily identical even though `u8` and `i8` have the same layout!
/// // assert!(mem::offset_of!(A, 1), mem::offset_of!(B, 1));
/// // assert_eq!(mem::offset_of!(A, 1), mem::offset_of!(B, 1));
///
/// #[repr(transparent)]
/// struct U8(u8);
@ -1345,12 +1345,12 @@ impl<T> SizedTypeProperties for T {}
/// type C = Wrapper<u8, U8>;
///
/// // Not necessarily identical even though `u8` and `U8` have the same layout!
/// // assert!(mem::offset_of!(A, 1), mem::offset_of!(C, 1));
/// // assert_eq!(mem::offset_of!(A, 1), mem::offset_of!(C, 1));
///
/// struct Empty<T>(core::marker::PhantomData<T>);
///
/// // Not necessarily identical even though `PhantomData` always has the same layout!
/// // assert!(mem::offset_of!(Empty<u8>, 0), mem::offset_of!(Empty<i8>, 0));
/// // assert_eq!(mem::offset_of!(Empty<u8>, 0), mem::offset_of!(Empty<i8>, 0));
/// ```
///
/// [explicit `repr` attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations

View File

@ -36,6 +36,7 @@ pub fn load(config: &Config) -> Self {
#[derive(Default)]
pub struct EarlyProps {
pub aux: Vec<String>,
pub aux_bin: Vec<String>,
pub aux_crate: Vec<(String, String)>,
pub revisions: Vec<String>,
}
@ -59,6 +60,12 @@ pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
r.trim().to_string()
});
config.push_name_value_directive(
ln,
directives::AUX_BIN,
&mut props.aux_bin,
|r| r.trim().to_string(),
);
config.push_name_value_directive(
ln,
directives::AUX_CRATE,
@ -95,6 +102,8 @@ pub struct TestProps {
// directory as the test, but for backwards compatibility reasons
// we also check the auxiliary directory)
pub aux_builds: Vec<String>,
// Auxiliary crates that should be compiled as `#![crate_type = "bin"]`.
pub aux_bins: Vec<String>,
// Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies
// to build and pass with the `--extern` flag.
pub aux_crates: Vec<(String, String)>,
@ -217,6 +226,7 @@ mod directives {
pub const PRETTY_EXPANDED: &'static str = "pretty-expanded";
pub const PRETTY_MODE: &'static str = "pretty-mode";
pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only";
pub const AUX_BIN: &'static str = "aux-bin";
pub const AUX_BUILD: &'static str = "aux-build";
pub const AUX_CRATE: &'static str = "aux-crate";
pub const EXEC_ENV: &'static str = "exec-env";
@ -252,6 +262,7 @@ pub fn new() -> Self {
run_flags: None,
pp_exact: None,
aux_builds: vec![],
aux_bins: vec![],
aux_crates: vec![],
revisions: vec![],
rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())],
@ -417,6 +428,9 @@ fn split_flags(flags: &str) -> Vec<String> {
config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
r.trim().to_string()
});
config.push_name_value_directive(ln, AUX_BIN, &mut self.aux_bins, |r| {
r.trim().to_string()
});
config.push_name_value_directive(
ln,
AUX_CRATE,
@ -683,6 +697,7 @@ pub fn line_directive<'line>(
const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
// tidy-alphabetical-start
"assembly-output",
"aux-bin",
"aux-build",
"aux-crate",
"build-aux-docs",

View File

@ -82,21 +82,21 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
}
/// The platform-specific library name
pub fn get_lib_name(lib: &str, dylib: bool) -> String {
// In some casess (e.g. MUSL), we build a static
// library, rather than a dynamic library.
// In this case, the only path we can pass
// with '--extern-meta' is the '.lib' file
if !dylib {
return format!("lib{}.rlib", lib);
}
if cfg!(windows) {
format!("{}.dll", lib)
} else if cfg!(target_os = "macos") {
format!("lib{}.dylib", lib)
} else {
format!("lib{}.so", lib)
fn get_lib_name(lib: &str, aux_type: AuxType) -> Option<String> {
match aux_type {
AuxType::Bin => None,
// In some cases (e.g. MUSL), we build a static
// library, rather than a dynamic library.
// In this case, the only path we can pass
// with '--extern-meta' is the '.rlib' file
AuxType::Lib => Some(format!("lib{}.rlib", lib)),
AuxType::Dylib => Some(if cfg!(windows) {
format!("{}.dll", lib)
} else if cfg!(target_os = "macos") {
format!("lib{}.dylib", lib)
} else {
format!("lib{}.so", lib)
}),
}
}
@ -2098,19 +2098,36 @@ fn aux_output_dir(&self) -> PathBuf {
create_dir_all(&aux_dir).unwrap();
}
if !self.props.aux_bins.is_empty() {
let aux_bin_dir = self.aux_bin_output_dir_name();
let _ = fs::remove_dir_all(&aux_bin_dir);
create_dir_all(&aux_bin_dir).unwrap();
}
aux_dir
}
fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
for rel_ab in &self.props.aux_builds {
self.build_auxiliary(of, rel_ab, &aux_dir);
self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */);
}
for rel_ab in &self.props.aux_bins {
self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */);
}
for (aux_name, aux_path) in &self.props.aux_crates {
let is_dylib = self.build_auxiliary(of, &aux_path, &aux_dir);
let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */);
let lib_name =
get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), is_dylib);
rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type);
if let Some(lib_name) = lib_name {
rustc.arg("--extern").arg(format!(
"{}={}/{}",
aux_name,
aux_dir.display(),
lib_name
));
}
}
}
@ -2129,12 +2146,23 @@ fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) ->
}
/// Builds an aux dependency.
///
/// Returns whether or not it is a dylib.
fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) -> bool {
fn build_auxiliary(
&self,
of: &TestPaths,
source_path: &str,
aux_dir: &Path,
is_bin: bool,
) -> AuxType {
let aux_testpaths = self.compute_aux_test_paths(of, source_path);
let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
let aux_output = TargetLocation::ThisDirectory(aux_dir.to_path_buf());
let mut aux_dir = aux_dir.to_path_buf();
if is_bin {
// On unix, the binary of `auxiliary/foo.rs` will be named
// `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so
// put bins in a `bin` subfolder.
aux_dir.push("bin");
}
let aux_output = TargetLocation::ThisDirectory(aux_dir.clone());
let aux_cx = TestCx {
config: self.config,
props: &aux_props,
@ -2152,15 +2180,17 @@ fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) ->
LinkToAux::No,
Vec::new(),
);
aux_cx.build_all_auxiliary(of, aux_dir, &mut aux_rustc);
aux_cx.build_all_auxiliary(of, &aux_dir, &mut aux_rustc);
for key in &aux_props.unset_rustc_env {
aux_rustc.env_remove(key);
}
aux_rustc.envs(aux_props.rustc_env.clone());
let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
(true, None)
let (aux_type, crate_type) = if is_bin {
(AuxType::Bin, Some("bin"))
} else if aux_props.no_prefer_dynamic {
(AuxType::Dylib, None)
} else if self.config.target.contains("emscripten")
|| (self.config.target.contains("musl")
&& !aux_props.force_host
@ -2185,9 +2215,9 @@ fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) ->
// Coverage tests want static linking by default so that coverage
// mappings in auxiliary libraries can be merged into the final
// executable.
(false, Some("lib"))
(AuxType::Lib, Some("lib"))
} else {
(true, Some("dylib"))
(AuxType::Dylib, Some("dylib"))
};
if let Some(crate_type) = crate_type {
@ -2211,7 +2241,7 @@ fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) ->
&auxres,
);
}
dylib
aux_type
}
fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) {
@ -2677,6 +2707,12 @@ fn aux_output_dir_name(&self) -> PathBuf {
.with_extra_extension(self.config.mode.aux_dir_disambiguator())
}
/// Gets the directory where auxiliary binaries are written.
/// E.g., `/.../testname.revision.mode/auxiliary/bin`.
fn aux_bin_output_dir_name(&self) -> PathBuf {
self.aux_output_dir_name().join("bin")
}
/// Generates a unique name for the test, such as `testname.revision.mode`.
fn output_testname_unique(&self) -> PathBuf {
output_testname_unique(self.config, self.testpaths, self.safe_revision())
@ -4826,3 +4862,9 @@ enum LinkToAux {
Yes,
No,
}
enum AuxType {
Bin,
Lib,
Dylib,
}

View File

@ -3463,7 +3463,6 @@
"ui/pattern/issue-106552.rs",
"ui/pattern/issue-106862.rs",
"ui/pattern/issue-110508.rs",
"ui/pattern/issue-114896.rs",
"ui/pattern/issue-115599.rs",
"ui/pattern/issue-11577.rs",
"ui/pattern/issue-117626.rs",

View File

@ -0,0 +1,11 @@
//@ build-fail
//@ needs-asm-support
#![feature(asm_const)]
use std::arch::global_asm;
fn main() {}
global_asm!("/* {} */", const 1 << 500); //~ ERROR evaluation of constant value failed [E0080]
global_asm!("/* {} */", const 1 / 0); //~ ERROR evaluation of constant value failed [E0080]

View File

@ -0,0 +1,15 @@
error[E0080]: evaluation of constant value failed
--> $DIR/fail-const-eval-issue-121099.rs:9:31
|
LL | global_asm!("/* {} */", const 1 << 500);
| ^^^^^^^^ attempt to shift left by `500_i32`, which would overflow
error[E0080]: evaluation of constant value failed
--> $DIR/fail-const-eval-issue-121099.rs:11:31
|
LL | global_asm!("/* {} */", const 1 / 0);
| ^^^^^ attempt to divide `1_i32` by zero
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -0,0 +1,14 @@
// Regression test for https://github.com/rust-lang/rust/issues/122581
// This used to ICE, because the union was unsized and the pointer casting code
// assumed that non-struct ADTs must be sized.
union Union {
val: std::mem::ManuallyDrop<[u8]>,
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
}
fn cast(ptr: *const ()) -> *const Union {
ptr as _
}
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/unsized-union-ice.rs:6:10
|
LL | val: std::mem::ManuallyDrop<[u8]>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `ManuallyDrop<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `ManuallyDrop<[u8]>: Sized`
note: required because it appears within the type `ManuallyDrop<[u8]>`
--> $SRC_DIR/core/src/mem/manually_drop.rs:LL:COL
= note: no field of a union may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | val: &std::mem::ManuallyDrop<[u8]>,
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | val: Box<std::mem::ManuallyDrop<[u8]>>,
| ++++ +
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,3 @@
fn main() {
println!("it works");
}

View File

@ -0,0 +1,9 @@
//@ ignore-cross-compile because we run the compiled code
//@ aux-bin: print-it-works.rs
//@ run-pass
fn main() {
let stdout =
std::process::Command::new("auxiliary/bin/print-it-works").output().unwrap().stdout;
assert_eq!(stdout, b"it works\n");
}

View File

@ -0,0 +1,10 @@
// Checks that there is a suggestion for simple tuple index access expression (used where an
// identifier is expected in a format arg) to use positional arg instead.
// Issue: <https://github.com/rust-lang/rust/issues/122535>.
//@ run-rustfix
fn main() {
let x = (1,);
println!("{0}", x.0);
//~^ ERROR invalid format string
}

View File

@ -0,0 +1,10 @@
// Checks that there is a suggestion for simple tuple index access expression (used where an
// identifier is expected in a format arg) to use positional arg instead.
// Issue: <https://github.com/rust-lang/rust/issues/122535>.
//@ run-rustfix
fn main() {
let x = (1,);
println!("{x.0}");
//~^ ERROR invalid format string
}

View File

@ -0,0 +1,13 @@
error: invalid format string: tuple index access isn't supported
--> $DIR/format-args-non-identifier-diagnostics.rs:8:16
|
LL | println!("{x.0}");
| ^^^ not supported in format string
|
help: consider using a positional formatting argument instead
|
LL | println!("{0}", x.0);
| ~ +++++
error: aborting due to 1 previous error

View File

@ -16,7 +16,6 @@ fn main() {
let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345
let _ = String::new(); //~ ERROR: unnecessary qualification
let _ = std::env::current_dir(); //~ ERROR: unnecessary qualification
let _: Vec<String> = Vec::<String>::new();
//~^ ERROR: unnecessary qualification
@ -27,7 +26,7 @@ fn main() {
let _: std::fmt::Result = Ok(());
// don't report unnecessary qualification because fix(#122373) for issue #121331
let _ = <bool as Default>::default(); // issue #121999
let _ = <bool as Default>::default(); // issue #121999 (modified)
//~^ ERROR: unnecessary qualification
macro_rules! m { ($a:ident, $b:ident) => {

View File

@ -16,7 +16,6 @@ fn main() {
let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345
let _ = std::string::String::new(); //~ ERROR: unnecessary qualification
let _ = ::std::env::current_dir(); //~ ERROR: unnecessary qualification
let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
//~^ ERROR: unnecessary qualification
@ -27,7 +26,7 @@ fn main() {
let _: std::fmt::Result = Ok(());
// don't report unnecessary qualification because fix(#122373) for issue #121331
let _ = <bool as ::std::default::Default>::default(); // issue #121999
let _ = <bool as std::default::Default>::default(); // issue #121999 (modified)
//~^ ERROR: unnecessary qualification
macro_rules! m { ($a:ident, $b:ident) => {

View File

@ -40,19 +40,7 @@ LL + let _ = String::new();
|
error: unnecessary qualification
--> $DIR/lint-qualification.rs:19:13
|
LL | let _ = ::std::env::current_dir();
| ^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove the unnecessary path segments
|
LL - let _ = ::std::env::current_dir();
LL + let _ = std::env::current_dir();
|
error: unnecessary qualification
--> $DIR/lint-qualification.rs:21:12
--> $DIR/lint-qualification.rs:20:12
|
LL | let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
| ^^^^^^^^^^^^^^^^^^^^^
@ -64,7 +52,7 @@ LL + let _: Vec<String> = std::vec::Vec::<String>::new();
|
error: unnecessary qualification
--> $DIR/lint-qualification.rs:21:36
--> $DIR/lint-qualification.rs:20:36
|
LL | let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -76,7 +64,7 @@ LL + let _: std::vec::Vec<String> = Vec::<String>::new();
|
error: unused import: `std::fmt`
--> $DIR/lint-qualification.rs:25:9
--> $DIR/lint-qualification.rs:24:9
|
LL | use std::fmt;
| ^^^^^^^^
@ -88,16 +76,16 @@ LL | #![deny(unused_imports)]
| ^^^^^^^^^^^^^^
error: unnecessary qualification
--> $DIR/lint-qualification.rs:30:13
--> $DIR/lint-qualification.rs:29:13
|
LL | let _ = <bool as ::std::default::Default>::default(); // issue #121999
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | let _ = <bool as std::default::Default>::default(); // issue #121999 (modified)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove the unnecessary path segments
|
LL - let _ = <bool as ::std::default::Default>::default(); // issue #121999
LL + let _ = <bool as Default>::default(); // issue #121999
LL - let _ = <bool as std::default::Default>::default(); // issue #121999 (modified)
LL + let _ = <bool as Default>::default(); // issue #121999 (modified)
|
error: aborting due to 8 previous errors
error: aborting due to 7 previous errors

View File

@ -0,0 +1,12 @@
// Checks that `unused_qualifications` don't fire on explicit global paths.
// Issue: <https://github.com/rust-lang/rust/issues/122374>.
//@ check-pass
#![deny(unused_qualifications)]
pub fn bar() -> u64 {
::std::default::Default::default()
}
fn main() {}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
//@ run-rustfix
#![allow(dead_code)]
fn main() {
fn x(a: &char) {
let &(mut b) = a;
b.make_ascii_uppercase();
//~^ cannot borrow `b` as mutable, as it is not declared as mutable
}
}

View File

@ -1,3 +1,6 @@
//@ run-rustfix
#![allow(dead_code)]
fn main() {
fn x(a: &char) {
let &b = a;

View File

@ -1,5 +1,5 @@
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
--> $DIR/issue-114896.rs:4:9
--> $DIR/patkind-ref-binding-issue-114896.rs:7:9
|
LL | let &b = a;
| -- help: consider changing this to be mutable: `&(mut b)`

View File

@ -0,0 +1,11 @@
//@ run-rustfix
#![allow(dead_code)]
fn mutate(_y: &mut i32) {}
fn foo(&(mut x): &i32) {
mutate(&mut x);
//~^ ERROR cannot borrow `x` as mutable
}
fn main() {}

View File

@ -0,0 +1,11 @@
//@ run-rustfix
#![allow(dead_code)]
fn mutate(_y: &mut i32) {}
fn foo(&x: &i32) {
mutate(&mut x);
//~^ ERROR cannot borrow `x` as mutable
}
fn main() {}

View File

@ -0,0 +1,11 @@
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
--> $DIR/patkind-ref-binding-issue-122415.rs:7:12
|
LL | fn foo(&x: &i32) {
| -- help: consider changing this to be mutable: `&(mut x)`
LL | mutate(&mut x);
| ^^^^^^ cannot borrow as mutable
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0596`.