mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Auto merge of #85036 - Dylan-DPC:rollup-4qfabo3, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #84254 (illumos should put libc last in library search order) - #84442 (Unify rustc and rustdoc parsing of `cfg()`) - #84655 (Cleanup of `wasm`) - #84866 (linker: Avoid library duplication with `/WHOLEARCHIVE`) - #84930 (rename LLVM target for RustyHermit) - #84991 (rustc: Support Rust-specific features in -Ctarget-feature) - #85029 (SGX mutex is movable) - #85030 (Rearrange SGX split module files) - #85033 (some further small cleanups) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ca712bc425
@ -339,24 +339,32 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
|
||||
Some(_) | None => {}
|
||||
};
|
||||
|
||||
let filter = |s: &str| {
|
||||
if s.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let feature = if s.starts_with("+") || s.starts_with("-") {
|
||||
&s[1..]
|
||||
} else {
|
||||
return Some(s.to_string());
|
||||
};
|
||||
// Rustc-specific feature requests like `+crt-static` or `-crt-static`
|
||||
// are not passed down to LLVM.
|
||||
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
|
||||
return None;
|
||||
}
|
||||
// ... otherwise though we run through `to_llvm_feature` feature when
|
||||
// passing requests down to LLVM. This means that all in-language
|
||||
// features also work on the command line instead of having two
|
||||
// different names when the LLVM name and the Rust name differ.
|
||||
Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature)))
|
||||
};
|
||||
|
||||
// Features implied by an implicit or explicit `--target`.
|
||||
features.extend(
|
||||
sess.target
|
||||
.features
|
||||
.split(',')
|
||||
.filter(|f| !f.is_empty() && !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)))
|
||||
.map(String::from),
|
||||
);
|
||||
features.extend(sess.target.features.split(',').filter_map(&filter));
|
||||
|
||||
// -Ctarget-features
|
||||
features.extend(
|
||||
sess.opts
|
||||
.cg
|
||||
.target_feature
|
||||
.split(',')
|
||||
.filter(|f| !f.is_empty() && !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)))
|
||||
.map(String::from),
|
||||
);
|
||||
features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter));
|
||||
|
||||
features
|
||||
}
|
||||
|
@ -340,6 +340,14 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
}
|
||||
|
||||
fn link_dylib(&mut self, lib: Symbol, verbatim: bool, as_needed: bool) {
|
||||
if self.sess.target.os == "illumos" && lib.as_str() == "c" {
|
||||
// libc will be added via late_link_args on illumos so that it will
|
||||
// appear last in the library search order.
|
||||
// FIXME: This should be replaced by a more complete and generic
|
||||
// mechanism for controlling the order of library arguments passed
|
||||
// to the linker.
|
||||
return;
|
||||
}
|
||||
if !as_needed {
|
||||
if self.sess.target.is_like_osx {
|
||||
// FIXME(81490): ld64 doesn't support these flags but macOS 11
|
||||
@ -813,11 +821,9 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: Symbol, verbatim: bool, _search_path: &[PathBuf]) {
|
||||
self.link_staticlib(lib, verbatim);
|
||||
self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" }));
|
||||
}
|
||||
fn link_whole_rlib(&mut self, path: &Path) {
|
||||
self.link_rlib(path);
|
||||
let mut arg = OsString::from("/WHOLEARCHIVE:");
|
||||
arg.push(path);
|
||||
self.cmd.arg(arg);
|
||||
|
@ -464,31 +464,9 @@ impl<'a> StripUnconfigured<'a> {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
let error = |span, msg, suggestion: &str| {
|
||||
let mut err = self.sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
|
||||
if !suggestion.is_empty() {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"expected syntax is",
|
||||
suggestion.into(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
true
|
||||
};
|
||||
let span = meta_item.span;
|
||||
match meta_item.meta_item_list() {
|
||||
None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
|
||||
Some([]) => error(span, "`cfg` predicate is not specified", ""),
|
||||
Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
|
||||
Some([single]) => match single.meta_item() {
|
||||
Some(meta_item) => {
|
||||
attr::cfg_matches(meta_item, &self.sess.parse_sess, self.features)
|
||||
}
|
||||
None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
|
||||
},
|
||||
}
|
||||
parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
|
||||
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.features)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -532,6 +510,32 @@ impl<'a> StripUnconfigured<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
|
||||
let error = |span, msg, suggestion: &str| {
|
||||
let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
|
||||
if !suggestion.is_empty() {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"expected syntax is",
|
||||
suggestion.into(),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
None
|
||||
};
|
||||
let span = meta_item.span;
|
||||
match meta_item.meta_item_list() {
|
||||
None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
|
||||
Some([]) => error(span, "`cfg` predicate is not specified", ""),
|
||||
Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
|
||||
Some([single]) => match single.meta_item() {
|
||||
Some(meta_item) => Some(meta_item),
|
||||
None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn is_cfg(sess: &Session, attr: &Attribute) -> bool {
|
||||
sess.check_name(attr, sym::cfg)
|
||||
}
|
||||
|
@ -6,6 +6,17 @@ pub fn opts() -> TargetOptions {
|
||||
late_link_args.insert(
|
||||
LinkerFlavor::Gcc,
|
||||
vec![
|
||||
// The illumos libc contains a stack unwinding implementation, as
|
||||
// does libgcc_s. The latter implementation includes several
|
||||
// additional symbols that are not always in base libc. To force
|
||||
// the consistent use of just one unwinder, we ensure libc appears
|
||||
// after libgcc_s in the NEEDED list for the resultant binary by
|
||||
// ignoring any attempts to add it as a dynamic dependency until the
|
||||
// very end.
|
||||
// FIXME: This should be replaced by a more complete and generic
|
||||
// mechanism for controlling the order of library arguments passed
|
||||
// to the linker.
|
||||
"-lc".to_string(),
|
||||
// LLVM will insert calls to the stack protector functions
|
||||
// "__stack_chk_fail" and "__stack_chk_guard" into code in native
|
||||
// object files. Some platforms include these symbols directly in
|
||||
|
@ -11,7 +11,7 @@ pub fn target() -> Target {
|
||||
base.stack_probes = StackProbeType::Call;
|
||||
|
||||
Target {
|
||||
llvm_target: "x86_64-unknown-none-elf".to_string(),
|
||||
llvm_target: "x86_64-unknown-hermit".to_string(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
.to_string(),
|
||||
|
@ -720,11 +720,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub(in super::super) fn select_obligations_where_possible(
|
||||
&self,
|
||||
fallback_has_occurred: bool,
|
||||
mutate_fullfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
|
||||
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
|
||||
) {
|
||||
let result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
|
||||
if let Err(mut errors) = result {
|
||||
mutate_fullfillment_errors(&mut errors);
|
||||
mutate_fulfillment_errors(&mut errors);
|
||||
self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
|
||||
}
|
||||
}
|
||||
|
@ -986,7 +986,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
error.obligation.predicate.kind().skip_binder()
|
||||
{
|
||||
// If any of the type arguments in this path segment caused the
|
||||
// `FullfillmentError`, point at its span (#61860).
|
||||
// `FulfillmentError`, point at its span (#61860).
|
||||
for arg in path
|
||||
.segments
|
||||
.iter()
|
||||
|
@ -43,7 +43,7 @@ struct CheckWfFcxBuilder<'tcx> {
|
||||
impl<'tcx> CheckWfFcxBuilder<'tcx> {
|
||||
fn with_fcx<F>(&mut self, f: F)
|
||||
where
|
||||
F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>, TyCtxt<'tcx>) -> Vec<Ty<'tcx>>,
|
||||
F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> Vec<Ty<'tcx>>,
|
||||
{
|
||||
let id = self.id;
|
||||
let span = self.span;
|
||||
@ -56,7 +56,7 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
|
||||
// empty `param_env`.
|
||||
check_false_global_bounds(&fcx, span, id);
|
||||
}
|
||||
let wf_tys = f(&fcx, fcx.tcx);
|
||||
let wf_tys = f(&fcx);
|
||||
fcx.select_all_obligations_or_error();
|
||||
fcx.regionck_item(id, span, &wf_tys);
|
||||
});
|
||||
@ -388,7 +388,7 @@ fn check_associated_item(
|
||||
debug!("check_associated_item: {:?}", item_id);
|
||||
|
||||
let code = ObligationCauseCode::MiscObligation;
|
||||
for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
|
||||
for_id(tcx, item_id, span).with_fcx(|fcx| {
|
||||
let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
|
||||
|
||||
let (mut implied_bounds, self_ty) = match item.container {
|
||||
@ -409,7 +409,6 @@ fn check_associated_item(
|
||||
let sig = fcx.normalize_associated_types_in(span, sig);
|
||||
let hir_sig = sig_if_method.expect("bad signature for method");
|
||||
check_fn_or_method(
|
||||
tcx,
|
||||
fcx,
|
||||
item.ident.span,
|
||||
sig,
|
||||
@ -467,9 +466,9 @@ fn check_type_defn<'tcx, F>(
|
||||
) where
|
||||
F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
|
||||
{
|
||||
for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
|
||||
for_item(tcx, item).with_fcx(|fcx| {
|
||||
let variants = lookup_fields(fcx);
|
||||
let packed = fcx.tcx.adt_def(item.def_id).repr.packed();
|
||||
let packed = tcx.adt_def(item.def_id).repr.packed();
|
||||
|
||||
for variant in &variants {
|
||||
// For DST, or when drop needs to copy things around, all
|
||||
@ -477,15 +476,14 @@ fn check_type_defn<'tcx, F>(
|
||||
let needs_drop_copy = || {
|
||||
packed && {
|
||||
let ty = variant.fields.last().unwrap().ty;
|
||||
let ty = fcx.tcx.erase_regions(ty);
|
||||
let ty = tcx.erase_regions(ty);
|
||||
if ty.needs_infer() {
|
||||
fcx_tcx
|
||||
.sess
|
||||
tcx.sess
|
||||
.delay_span_bug(item.span, &format!("inference variables in {:?}", ty));
|
||||
// Just treat unresolved type expression as if it needs drop.
|
||||
true
|
||||
} else {
|
||||
ty.needs_drop(fcx_tcx, fcx_tcx.param_env(item.def_id))
|
||||
ty.needs_drop(tcx, tcx.param_env(item.def_id))
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -497,7 +495,7 @@ fn check_type_defn<'tcx, F>(
|
||||
let last = idx == variant.fields.len() - 1;
|
||||
fcx.register_bound(
|
||||
field.ty,
|
||||
fcx.tcx.require_lang_item(LangItem::Sized, None),
|
||||
tcx.require_lang_item(LangItem::Sized, None),
|
||||
traits::ObligationCause::new(
|
||||
field.span,
|
||||
fcx.body_id,
|
||||
@ -524,11 +522,10 @@ fn check_type_defn<'tcx, F>(
|
||||
|
||||
// Explicit `enum` discriminant values must const-evaluate successfully.
|
||||
if let Some(discr_def_id) = variant.explicit_discr {
|
||||
let discr_substs =
|
||||
InternalSubsts::identity_for_item(fcx.tcx, discr_def_id.to_def_id());
|
||||
let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
|
||||
|
||||
let cause = traits::ObligationCause::new(
|
||||
fcx.tcx.def_span(discr_def_id),
|
||||
tcx.def_span(discr_def_id),
|
||||
fcx.body_id,
|
||||
traits::MiscObligation,
|
||||
);
|
||||
@ -539,12 +536,12 @@ fn check_type_defn<'tcx, F>(
|
||||
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
|
||||
discr_substs,
|
||||
)
|
||||
.to_predicate(fcx.tcx),
|
||||
.to_predicate(tcx),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
|
||||
check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
|
||||
|
||||
// No implied bounds in a struct definition.
|
||||
vec![]
|
||||
@ -569,8 +566,9 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
for_item(tcx, item).with_fcx(|fcx, _| {
|
||||
check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
|
||||
// FIXME: this shouldn't use an `FnCtxt` at all.
|
||||
for_item(tcx, item).with_fcx(|fcx| {
|
||||
check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
|
||||
|
||||
vec![]
|
||||
});
|
||||
@ -610,20 +608,12 @@ fn check_item_fn(
|
||||
span: Span,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
) {
|
||||
for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
|
||||
let def_id = fcx.tcx.hir().local_def_id(item_id);
|
||||
let sig = fcx.tcx.fn_sig(def_id);
|
||||
for_id(tcx, item_id, span).with_fcx(|fcx| {
|
||||
let def_id = tcx.hir().local_def_id(item_id);
|
||||
let sig = tcx.fn_sig(def_id);
|
||||
let sig = fcx.normalize_associated_types_in(span, sig);
|
||||
let mut implied_bounds = vec![];
|
||||
check_fn_or_method(
|
||||
tcx,
|
||||
fcx,
|
||||
ident.span,
|
||||
sig,
|
||||
decl,
|
||||
def_id.to_def_id(),
|
||||
&mut implied_bounds,
|
||||
);
|
||||
check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
|
||||
implied_bounds
|
||||
})
|
||||
}
|
||||
@ -631,7 +621,7 @@ fn check_item_fn(
|
||||
fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_foreign_ty: bool) {
|
||||
debug!("check_item_type: {:?}", item_id);
|
||||
|
||||
for_id(tcx, item_id, ty_span).with_fcx(|fcx, tcx| {
|
||||
for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
|
||||
let ty = tcx.type_of(tcx.hir().local_def_id(item_id));
|
||||
let item_ty = fcx.normalize_associated_types_in(ty_span, ty);
|
||||
|
||||
@ -647,7 +637,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
|
||||
if forbid_unsized {
|
||||
fcx.register_bound(
|
||||
item_ty,
|
||||
fcx.tcx.require_lang_item(LangItem::Sized, None),
|
||||
tcx.require_lang_item(LangItem::Sized, None),
|
||||
traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation),
|
||||
);
|
||||
}
|
||||
@ -665,13 +655,13 @@ fn check_impl<'tcx>(
|
||||
) {
|
||||
debug!("check_impl: {:?}", item);
|
||||
|
||||
for_item(tcx, item).with_fcx(|fcx, tcx| {
|
||||
for_item(tcx, item).with_fcx(|fcx| {
|
||||
match *ast_trait_ref {
|
||||
Some(ref ast_trait_ref) => {
|
||||
// `#[rustc_reservation_impl]` impls are not real impls and
|
||||
// therefore don't need to be WF (the trait's `Self: Trait` predicate
|
||||
// won't hold).
|
||||
let trait_ref = fcx.tcx.impl_trait_ref(item.def_id).unwrap();
|
||||
let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
|
||||
let trait_ref =
|
||||
fcx.normalize_associated_types_in(ast_trait_ref.path.span, trait_ref);
|
||||
let obligations = traits::wf::trait_obligations(
|
||||
@ -687,7 +677,7 @@ fn check_impl<'tcx>(
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let self_ty = fcx.tcx.type_of(item.def_id);
|
||||
let self_ty = tcx.type_of(item.def_id);
|
||||
let self_ty = fcx.normalize_associated_types_in(item.span, self_ty);
|
||||
fcx.register_wf_obligation(
|
||||
self_ty.into(),
|
||||
@ -697,7 +687,7 @@ fn check_impl<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
|
||||
check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
|
||||
|
||||
fcx.impl_implied_bounds(item.def_id.to_def_id(), item.span)
|
||||
});
|
||||
@ -705,15 +695,15 @@ fn check_impl<'tcx>(
|
||||
|
||||
/// Checks where-clauses and inline bounds that are declared on `def_id`.
|
||||
fn check_where_clauses<'tcx, 'fcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fcx: &FnCtxt<'fcx, 'tcx>,
|
||||
span: Span,
|
||||
def_id: DefId,
|
||||
return_ty: Option<(Ty<'tcx>, Span)>,
|
||||
) {
|
||||
debug!("check_where_clauses(def_id={:?}, return_ty={:?})", def_id, return_ty);
|
||||
let tcx = fcx.tcx;
|
||||
|
||||
let predicates = fcx.tcx.predicates_of(def_id);
|
||||
let predicates = tcx.predicates_of(def_id);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
|
||||
let is_our_default = |def: &ty::GenericParamDef| match def.kind {
|
||||
@ -734,14 +724,14 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
if is_our_default(¶m) {
|
||||
let ty = fcx.tcx.type_of(param.def_id);
|
||||
let ty = tcx.type_of(param.def_id);
|
||||
// Ignore dependent defaults -- that is, where the default of one type
|
||||
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
|
||||
// be sure if it will error or not as user might always specify the other.
|
||||
if !ty.needs_subst() {
|
||||
fcx.register_wf_obligation(
|
||||
ty.into(),
|
||||
fcx.tcx.def_span(param.def_id),
|
||||
tcx.def_span(param.def_id),
|
||||
ObligationCauseCode::MiscObligation,
|
||||
);
|
||||
}
|
||||
@ -754,7 +744,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
let default_ct = tcx.const_param_default(param.def_id);
|
||||
fcx.register_wf_obligation(
|
||||
default_ct.into(),
|
||||
fcx.tcx.def_span(param.def_id),
|
||||
tcx.def_span(param.def_id),
|
||||
ObligationCauseCode::MiscObligation,
|
||||
);
|
||||
}
|
||||
@ -772,17 +762,17 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
|
||||
//
|
||||
// First we build the defaulted substitution.
|
||||
let substs = InternalSubsts::for_item(fcx.tcx, def_id, |param, _| {
|
||||
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
// All regions are identity.
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
tcx.mk_param_from_def(param)
|
||||
}
|
||||
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
// If the param has a default, ...
|
||||
if is_our_default(param) {
|
||||
let default_ty = fcx.tcx.type_of(param.def_id);
|
||||
let default_ty = tcx.type_of(param.def_id);
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ty.needs_subst() {
|
||||
// ... then substitute it with the default.
|
||||
@ -790,7 +780,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
tcx.mk_param_from_def(param)
|
||||
}
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
// FIXME(const_generics_defaults): I(@lcnr) feel like always
|
||||
@ -811,7 +801,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
tcx.mk_param_from_def(param)
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -848,7 +838,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
}
|
||||
let mut param_count = CountParams::default();
|
||||
let has_region = pred.visit_with(&mut param_count).is_break();
|
||||
let substituted_pred = pred.subst(fcx.tcx, substs);
|
||||
let substituted_pred = pred.subst(tcx, substs);
|
||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||
// or preds with multiple params.
|
||||
if substituted_pred.has_param_types_or_consts()
|
||||
@ -879,14 +869,14 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
traits::Obligation::new(cause, fcx.param_env, pred)
|
||||
});
|
||||
|
||||
let predicates = predicates.instantiate_identity(fcx.tcx);
|
||||
let predicates = predicates.instantiate_identity(tcx);
|
||||
|
||||
if let Some((mut return_ty, span)) = return_ty {
|
||||
if return_ty.has_infer_types_or_consts() {
|
||||
fcx.select_obligations_where_possible(false, |_| {});
|
||||
return_ty = fcx.resolve_vars_if_possible(return_ty);
|
||||
}
|
||||
check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
|
||||
check_opaque_types(fcx, def_id.expect_local(), span, return_ty);
|
||||
}
|
||||
|
||||
let predicates = fcx.normalize_associated_types_in(span, predicates);
|
||||
@ -905,7 +895,6 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
}
|
||||
|
||||
fn check_fn_or_method<'fcx, 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fcx: &FnCtxt<'fcx, 'tcx>,
|
||||
span: Span,
|
||||
sig: ty::PolyFnSig<'tcx>,
|
||||
@ -930,7 +919,7 @@ fn check_fn_or_method<'fcx, 'tcx>(
|
||||
// FIXME(#25759) return types should not be implied bounds
|
||||
implied_bounds.push(sig.output());
|
||||
|
||||
check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
|
||||
check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
|
||||
}
|
||||
|
||||
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
|
||||
@ -953,15 +942,16 @@ fn check_fn_or_method<'fcx, 'tcx>(
|
||||
/// ```
|
||||
///
|
||||
fn check_opaque_types<'fcx, 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fcx: &FnCtxt<'fcx, 'tcx>,
|
||||
fn_def_id: LocalDefId,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
) {
|
||||
trace!("check_opaque_types(ty={:?})", ty);
|
||||
trace!("check_opaque_types(fn_def_id={:?}, ty={:?})", fn_def_id, ty);
|
||||
let tcx = fcx.tcx;
|
||||
|
||||
ty.fold_with(&mut ty::fold::BottomUpFolder {
|
||||
tcx: fcx.tcx,
|
||||
tcx,
|
||||
ty_op: |ty| {
|
||||
if let ty::Opaque(def_id, substs) = *ty.kind() {
|
||||
trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
|
||||
|
@ -8,7 +8,7 @@ pub struct Mutex {
|
||||
inner: SpinMutex<WaitVariable<bool>>,
|
||||
}
|
||||
|
||||
pub type MovableMutex = Box<Mutex>;
|
||||
pub type MovableMutex = Mutex;
|
||||
|
||||
// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
|
||||
impl Mutex {
|
||||
|
@ -13,13 +13,8 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// A doubly-linked list where callers are in charge of memory allocation
|
||||
/// of the nodes in the list.
|
||||
mod unsafe_list;
|
||||
|
||||
/// Trivial spinlock-based implementation of `sync::Mutex`.
|
||||
// FIXME: Perhaps use Intel TSX to avoid locking?
|
||||
mod spin_mutex;
|
||||
mod unsafe_list;
|
||||
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{Deref, DerefMut};
|
@ -1,3 +1,6 @@
|
||||
//! Trivial spinlock-based implementation of `sync::Mutex`.
|
||||
// FIXME: Perhaps use Intel TSX to avoid locking?
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
//! A doubly-linked list where callers are in charge of memory allocation
|
||||
//! of the nodes in the list.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
|
||||
pub struct Args {}
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::vec;
|
||||
|
||||
pub fn args() -> Args {
|
||||
Args { iter: Vec::new().into_iter() }
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
}
|
||||
|
||||
impl !Send for Args {}
|
||||
impl !Sync for Args {}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.iter.as_slice().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.iter.next_back()
|
||||
}
|
||||
}
|
@ -13,20 +13,10 @@ impl Thread {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn yield_now() {
|
||||
// do nothing
|
||||
}
|
||||
pub fn yield_now() {}
|
||||
|
||||
pub fn set_name(_name: &CStr) {
|
||||
// nope
|
||||
}
|
||||
pub fn set_name(_name: &CStr) {}
|
||||
|
||||
#[cfg(not(target_feature = "atomics"))]
|
||||
pub fn sleep(_dur: Duration) {
|
||||
panic!("can't sleep");
|
||||
}
|
||||
|
||||
#[cfg(target_feature = "atomics")]
|
||||
pub fn sleep(dur: Duration) {
|
||||
use crate::arch::wasm32;
|
||||
use crate::cmp;
|
||||
@ -46,9 +36,7 @@ impl Thread {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join(self) {
|
||||
self.0
|
||||
}
|
||||
pub fn join(self) {}
|
||||
}
|
||||
|
||||
pub mod guard {
|
||||
@ -61,11 +49,9 @@ pub mod guard {
|
||||
}
|
||||
}
|
||||
|
||||
// This is only used by atomics primitives when the `atomics` feature is
|
||||
// enabled. In that mode we currently just use our own thread-local to store our
|
||||
// We currently just use our own thread-local to store our
|
||||
// current thread's ID, and then we lazily initialize it to something allocated
|
||||
// from a global counter.
|
||||
#[cfg(target_feature = "atomics")]
|
||||
pub fn my_id() -> u32 {
|
||||
use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};
|
||||
|
@ -17,6 +17,7 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod alloc;
|
||||
#[path = "../unsupported/args.rs"]
|
||||
pub mod args;
|
||||
#[path = "../unix/cmath.rs"]
|
||||
pub mod cmath;
|
||||
@ -37,7 +38,6 @@ pub mod pipe;
|
||||
pub mod process;
|
||||
#[path = "../unsupported/stdio.rs"]
|
||||
pub mod stdio;
|
||||
pub mod thread;
|
||||
#[path = "../unsupported/thread_local_dtor.rs"]
|
||||
pub mod thread_local_dtor;
|
||||
#[path = "../unsupported/thread_local_key.rs"]
|
||||
@ -49,14 +49,16 @@ pub use crate::sys_common::os_str_bytes as os_str;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_feature = "atomics")] {
|
||||
#[path = "condvar_atomics.rs"]
|
||||
#[path = "atomics/condvar.rs"]
|
||||
pub mod condvar;
|
||||
#[path = "mutex_atomics.rs"]
|
||||
#[path = "atomics/mutex.rs"]
|
||||
pub mod mutex;
|
||||
#[path = "rwlock_atomics.rs"]
|
||||
#[path = "atomics/rwlock.rs"]
|
||||
pub mod rwlock;
|
||||
#[path = "futex_atomics.rs"]
|
||||
#[path = "atomics/futex.rs"]
|
||||
pub mod futex;
|
||||
#[path = "atomics/thread.rs"]
|
||||
pub mod thread;
|
||||
} else {
|
||||
#[path = "../unsupported/condvar.rs"]
|
||||
pub mod condvar;
|
||||
@ -64,6 +66,8 @@ cfg_if::cfg_if! {
|
||||
pub mod mutex;
|
||||
#[path = "../unsupported/rwlock.rs"]
|
||||
pub mod rwlock;
|
||||
#[path = "../unsupported/thread.rs"]
|
||||
pub mod thread;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,10 +317,10 @@ fn merge_attrs(
|
||||
} else {
|
||||
Attributes::from_ast(&both, None)
|
||||
},
|
||||
both.cfg(cx.sess().diagnostic()),
|
||||
both.cfg(cx.sess()),
|
||||
)
|
||||
} else {
|
||||
(old_attrs.clean(cx), old_attrs.cfg(cx.sess().diagnostic()))
|
||||
(old_attrs.clean(cx), old_attrs.cfg(cx.sess()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2018,7 +2018,7 @@ fn clean_extern_crate(
|
||||
def_id: crate_def_id.into(),
|
||||
visibility: krate.vis.clean(cx),
|
||||
kind: box ExternCrateItem { src: orig_name },
|
||||
cfg: attrs.cfg(cx.sess().diagnostic()),
|
||||
cfg: attrs.cfg(cx.sess()),
|
||||
}]
|
||||
}
|
||||
|
||||
|
@ -444,7 +444,7 @@ impl Item {
|
||||
kind,
|
||||
box ast_attrs.clean(cx),
|
||||
cx,
|
||||
ast_attrs.cfg(cx.sess().diagnostic()),
|
||||
ast_attrs.cfg(cx.sess()),
|
||||
)
|
||||
}
|
||||
|
||||
@ -456,7 +456,7 @@ impl Item {
|
||||
cx: &mut DocContext<'_>,
|
||||
cfg: Option<Arc<Cfg>>,
|
||||
) -> Item {
|
||||
debug!("name={:?}, def_id={:?}", name, def_id);
|
||||
trace!("name={:?}, def_id={:?}", name, def_id);
|
||||
|
||||
Item {
|
||||
def_id: def_id.into(),
|
||||
@ -795,7 +795,7 @@ crate trait AttributesExt {
|
||||
|
||||
fn other_attrs(&self) -> Vec<ast::Attribute>;
|
||||
|
||||
fn cfg(&self, diagnostic: &::rustc_errors::Handler) -> Option<Arc<Cfg>>;
|
||||
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
|
||||
}
|
||||
|
||||
impl AttributesExt for [ast::Attribute] {
|
||||
@ -820,17 +820,28 @@ impl AttributesExt for [ast::Attribute] {
|
||||
self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
|
||||
}
|
||||
|
||||
fn cfg(&self, diagnostic: &::rustc_errors::Handler) -> Option<Arc<Cfg>> {
|
||||
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
|
||||
let mut cfg = Cfg::True;
|
||||
|
||||
for attr in self.iter() {
|
||||
// #[doc]
|
||||
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
||||
if let Some(mi) = attr.meta() {
|
||||
if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
|
||||
// Extracted #[doc(cfg(...))]
|
||||
match Cfg::parse(cfg_mi) {
|
||||
Ok(new_cfg) => cfg &= new_cfg,
|
||||
Err(e) => diagnostic.span_err(e.span, e.msg),
|
||||
// #[doc(...)]
|
||||
if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
|
||||
for item in list {
|
||||
// #[doc(include)]
|
||||
if !item.has_name(sym::cfg) {
|
||||
continue;
|
||||
}
|
||||
// #[doc(cfg(...))]
|
||||
if let Some(cfg_mi) = item
|
||||
.meta_item()
|
||||
.and_then(|item| rustc_expand::config::parse_cfg(&item, sess))
|
||||
{
|
||||
match Cfg::parse(&cfg_mi) {
|
||||
Ok(new_cfg) => cfg &= new_cfg,
|
||||
Err(e) => sess.span_err(e.span, e.msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -997,29 +1008,6 @@ impl Attributes {
|
||||
self.other_attrs.lists(name)
|
||||
}
|
||||
|
||||
/// Extracts the content from an attribute `#[doc(cfg(content))]`.
|
||||
crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
|
||||
use rustc_ast::NestedMetaItem::MetaItem;
|
||||
|
||||
if let ast::MetaItemKind::List(ref nmis) = mi.kind {
|
||||
if nmis.len() == 1 {
|
||||
if let MetaItem(ref cfg_mi) = nmis[0] {
|
||||
if cfg_mi.has_name(sym::cfg) {
|
||||
if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
|
||||
if cfg_nmis.len() == 1 {
|
||||
if let MetaItem(ref content_mi) = cfg_nmis[0] {
|
||||
return Some(content_mi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Reads a `MetaItem` from within an attribute, looks for whether it is a
|
||||
/// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
|
||||
/// its expansion.
|
||||
|
@ -1096,7 +1096,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
|
||||
let ast_attrs = self.tcx.hir().attrs(hir_id);
|
||||
let mut attrs = Attributes::from_ast(ast_attrs, None);
|
||||
|
||||
if let Some(ref cfg) = ast_attrs.cfg(self.sess.diagnostic()) {
|
||||
if let Some(ref cfg) = ast_attrs.cfg(self.sess) {
|
||||
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
|
||||
return;
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ impl<'tcx> Context<'tcx> {
|
||||
&self.cache
|
||||
}
|
||||
|
||||
fn sess(&self) -> &'tcx Session {
|
||||
pub(super) fn sess(&self) -> &'tcx Session {
|
||||
&self.shared.tcx.sess
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
let import_item = clean::Item {
|
||||
def_id: import_def_id.into(),
|
||||
attrs: import_attrs,
|
||||
cfg: ast_attrs.cfg(cx.tcx().sess.diagnostic()),
|
||||
cfg: ast_attrs.cfg(cx.sess()),
|
||||
..myitem.clone()
|
||||
};
|
||||
|
||||
|
4
src/test/rustdoc-ui/invalid-cfg.rs
Normal file
4
src/test/rustdoc-ui/invalid-cfg.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#![feature(doc_cfg)]
|
||||
#[doc(cfg = "x")] //~ ERROR not followed by parentheses
|
||||
#[doc(cfg(x, y))] //~ ERROR multiple `cfg` predicates
|
||||
struct S {}
|
14
src/test/rustdoc-ui/invalid-cfg.stderr
Normal file
14
src/test/rustdoc-ui/invalid-cfg.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: `cfg` is not followed by parentheses
|
||||
--> $DIR/invalid-cfg.rs:2:7
|
||||
|
|
||||
LL | #[doc(cfg = "x")]
|
||||
| ^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
|
||||
|
||||
error: multiple `cfg` predicates are specified
|
||||
--> $DIR/invalid-cfg.rs:3:14
|
||||
|
|
||||
LL | #[doc(cfg(x, y))]
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -91,3 +91,11 @@ pub unsafe fn uses_target_feature() {
|
||||
pub fn uses_cfg_target_feature() {
|
||||
uses_target_feature();
|
||||
}
|
||||
|
||||
// multiple attributes should be allowed
|
||||
// @has doc_cfg/fn.multiple_attrs.html \
|
||||
// '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
|
||||
// 'This is supported on x and y and z only.'
|
||||
#[doc(inline, cfg(x))]
|
||||
#[doc(cfg(y), cfg(z))]
|
||||
pub fn multiple_attrs() {}
|
||||
|
@ -0,0 +1,5 @@
|
||||
// build-pass
|
||||
// only-x86
|
||||
// compile-flags: -C target-feature=+pclmulqdq
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user