Auto merge of #108934 - matthiaskrgr:rollup-vm414p5, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #106915 (Only load one CSS theme by default) - #108294 (Place binder correctly for arbitrary trait bound suggestion) - #108778 (x fmt: Don't print all modified files if there's more than 10) - #108854 (feat/refactor: improve errors in case of ident with number at start) - #108870 (Fix invalid inlining of reexport of reexport of private item) - #108917 (Consider target_family as pal) - #108922 (Add auto notification for changes to stable mir) - #108929 (Fix typo in span_map.rs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
104f4300cf
@ -117,7 +117,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let param_name = trait_pred.skip_binder().self_ty().to_string();
|
let param_name = trait_pred.skip_binder().self_ty().to_string();
|
||||||
let mut constraint = trait_pred.print_modifiers_and_trait_path().to_string();
|
let mut constraint = trait_pred.to_string();
|
||||||
|
|
||||||
if let Some((name, term)) = associated_ty {
|
if let Some((name, term)) = associated_ty {
|
||||||
// FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
|
// FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
|
||||||
@ -144,7 +144,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
|
|||||||
this requirement",
|
this requirement",
|
||||||
if generics.where_clause_span.is_empty() { "introducing a" } else { "extending the" },
|
if generics.where_clause_span.is_empty() { "introducing a" } else { "extending the" },
|
||||||
),
|
),
|
||||||
format!("{} {}: {}", generics.add_where_or_trailing_comma(), param_name, constraint),
|
format!("{} {constraint}", generics.add_where_or_trailing_comma()),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
true
|
true
|
||||||
|
@ -412,8 +412,7 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
|
|||||||
*[false] a
|
*[false] a
|
||||||
} `for` parameter list
|
} `for` parameter list
|
||||||
|
|
||||||
parse_invalid_identifier_with_leading_number = expected identifier, found number literal
|
parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
|
||||||
.label = identifiers cannot start with a number
|
|
||||||
|
|
||||||
parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
|
parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
|
||||||
.suggestion = replace `fn` with `impl` here
|
.suggestion = replace `fn` with `impl` here
|
||||||
|
@ -939,6 +939,7 @@ pub(crate) struct ExpectedIdentifier {
|
|||||||
pub token: Token,
|
pub token: Token,
|
||||||
pub suggest_raw: Option<SuggEscapeToUseAsIdentifier>,
|
pub suggest_raw: Option<SuggEscapeToUseAsIdentifier>,
|
||||||
pub suggest_remove_comma: Option<SuggRemoveComma>,
|
pub suggest_remove_comma: Option<SuggRemoveComma>,
|
||||||
|
pub help_cannot_start_number: Option<HelpIdentifierStartsWithNumber>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
|
||||||
@ -975,10 +976,18 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
|
|||||||
sugg.add_to_diagnostic(&mut diag);
|
sugg.add_to_diagnostic(&mut diag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(help) = self.help_cannot_start_number {
|
||||||
|
help.add_to_diagnostic(&mut diag);
|
||||||
|
}
|
||||||
|
|
||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[help(parse_invalid_identifier_with_leading_number)]
|
||||||
|
pub(crate) struct HelpIdentifierStartsWithNumber;
|
||||||
|
|
||||||
pub(crate) struct ExpectedSemi {
|
pub(crate) struct ExpectedSemi {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub token: Token,
|
pub token: Token,
|
||||||
@ -1207,14 +1216,6 @@ pub(crate) struct SelfParamNotFirst {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(parse_invalid_identifier_with_leading_number)]
|
|
||||||
pub(crate) struct InvalidIdentiferStartsWithNumber {
|
|
||||||
#[primary_span]
|
|
||||||
#[label]
|
|
||||||
pub span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_const_generic_without_braces)]
|
#[diag(parse_const_generic_without_braces)]
|
||||||
pub(crate) struct ConstGenericWithoutBraces {
|
pub(crate) struct ConstGenericWithoutBraces {
|
||||||
|
@ -8,14 +8,14 @@ use crate::errors::{
|
|||||||
ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
|
ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
|
||||||
ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentOnParamType,
|
ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentOnParamType,
|
||||||
DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
||||||
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, InInTypo,
|
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
|
||||||
IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, ParenthesesInForHead,
|
HelpIdentifierStartsWithNumber, InInTypo, IncorrectAwait, IncorrectSemicolon,
|
||||||
ParenthesesInForHeadSugg, PatternMethodParamWithoutBody, QuestionMarkInType,
|
IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg,
|
||||||
QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
|
PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst,
|
||||||
StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg,
|
StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens,
|
||||||
SuggEscapeToUseAsIdentifier, SuggRemoveComma, UnexpectedConstInGenericParam,
|
StructLiteralNeedingParensSugg, SuggEscapeToUseAsIdentifier, SuggRemoveComma,
|
||||||
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
|
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
|
||||||
UseEqInstead,
|
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::fluent_generated as fluent;
|
use crate::fluent_generated as fluent;
|
||||||
@ -280,6 +280,7 @@ impl<'a> Parser<'a> {
|
|||||||
TokenKind::CloseDelim(Delimiter::Brace),
|
TokenKind::CloseDelim(Delimiter::Brace),
|
||||||
TokenKind::CloseDelim(Delimiter::Parenthesis),
|
TokenKind::CloseDelim(Delimiter::Parenthesis),
|
||||||
];
|
];
|
||||||
|
|
||||||
let suggest_raw = match self.token.ident() {
|
let suggest_raw = match self.token.ident() {
|
||||||
Some((ident, false))
|
Some((ident, false))
|
||||||
if ident.is_raw_guess()
|
if ident.is_raw_guess()
|
||||||
@ -295,18 +296,19 @@ impl<'a> Parser<'a> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let suggest_remove_comma =
|
let suggest_remove_comma = (self.token == token::Comma
|
||||||
if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
|
&& self.look_ahead(1, |t| t.is_ident()))
|
||||||
Some(SuggRemoveComma { span: self.token.span })
|
.then_some(SuggRemoveComma { span: self.token.span });
|
||||||
} else {
|
|
||||||
None
|
let help_cannot_start_number =
|
||||||
};
|
self.is_lit_bad_ident().then_some(HelpIdentifierStartsWithNumber);
|
||||||
|
|
||||||
let err = ExpectedIdentifier {
|
let err = ExpectedIdentifier {
|
||||||
span: self.token.span,
|
span: self.token.span,
|
||||||
token: self.token.clone(),
|
token: self.token.clone(),
|
||||||
suggest_raw,
|
suggest_raw,
|
||||||
suggest_remove_comma,
|
suggest_remove_comma,
|
||||||
|
help_cannot_start_number,
|
||||||
};
|
};
|
||||||
let mut err = err.into_diagnostic(&self.sess.span_diagnostic);
|
let mut err = err.into_diagnostic(&self.sess.span_diagnostic);
|
||||||
|
|
||||||
@ -365,6 +367,17 @@ impl<'a> Parser<'a> {
|
|||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the current token is a integer or float literal and looks like
|
||||||
|
/// it could be a invalid identifier with digits at the start.
|
||||||
|
pub(super) fn is_lit_bad_ident(&mut self) -> bool {
|
||||||
|
matches!(self.token.uninterpolate().kind, token::Literal(Lit { kind: token::LitKind::Integer | token::LitKind::Float, .. })
|
||||||
|
// ensure that the integer literal is followed by a *invalid*
|
||||||
|
// suffix: this is how we know that it is a identifier with an
|
||||||
|
// invalid beginning.
|
||||||
|
if rustc_ast::MetaItemLit::from_token(&self.token).is_none()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn expected_one_of_not_found(
|
pub(super) fn expected_one_of_not_found(
|
||||||
&mut self,
|
&mut self,
|
||||||
edible: &[TokenKind],
|
edible: &[TokenKind],
|
||||||
|
@ -348,6 +348,10 @@ impl<'a> Parser<'a> {
|
|||||||
lo = self.token.span;
|
lo = self.token.span;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.is_lit_bad_ident() {
|
||||||
|
return Err(self.expected_ident_found());
|
||||||
|
}
|
||||||
|
|
||||||
let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd {
|
let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd {
|
||||||
self.parse_pat_deref(expected)?
|
self.parse_pat_deref(expected)?
|
||||||
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||||
|
@ -273,7 +273,6 @@ impl<'a> Parser<'a> {
|
|||||||
self.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.report_invalid_identifier_error()?;
|
|
||||||
let (pat, colon) =
|
let (pat, colon) =
|
||||||
self.parse_pat_before_ty(None, RecoverComma::Yes, PatternLocation::LetBinding)?;
|
self.parse_pat_before_ty(None, RecoverComma::Yes, PatternLocation::LetBinding)?;
|
||||||
|
|
||||||
@ -366,17 +365,6 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(P(ast::Local { ty, pat, kind, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
|
Ok(P(ast::Local { ty, pat, kind, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// report error for `let 1x = 123`
|
|
||||||
pub fn report_invalid_identifier_error(&mut self) -> PResult<'a, ()> {
|
|
||||||
if let token::Literal(lit) = self.token.uninterpolate().kind &&
|
|
||||||
rustc_ast::MetaItemLit::from_token(&self.token).is_none() &&
|
|
||||||
(lit.kind == token::LitKind::Integer || lit.kind == token::LitKind::Float) &&
|
|
||||||
self.look_ahead(1, |t| matches!(t.kind, token::Eq) || matches!(t.kind, token::Colon ) ) {
|
|
||||||
return Err(self.sess.create_err(errors::InvalidIdentiferStartsWithNumber { span: self.token.span }));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
|
fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
|
||||||
if let ast::ExprKind::Binary(op, ..) = init.kind {
|
if let ast::ExprKind::Binary(op, ..) = init.kind {
|
||||||
if op.node.lazy() {
|
if op.node.lazy() {
|
||||||
|
@ -165,8 +165,14 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
|
|||||||
if !CiEnv::is_ci() && paths.is_empty() {
|
if !CiEnv::is_ci() && paths.is_empty() {
|
||||||
match get_modified_rs_files(build) {
|
match get_modified_rs_files(build) {
|
||||||
Ok(Some(files)) => {
|
Ok(Some(files)) => {
|
||||||
|
if files.len() <= 10 {
|
||||||
|
for file in &files {
|
||||||
|
println!("formatting modified file {file}");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("formatting {} modified files", files.len());
|
||||||
|
}
|
||||||
for file in files {
|
for file in files {
|
||||||
println!("formatting modified file {file}");
|
|
||||||
ignore_fmt.add(&format!("/{file}")).expect(&file);
|
ignore_fmt.add(&format!("/{file}")).expect(&file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2065,23 +2065,81 @@ fn clean_bare_fn_ty<'tcx>(
|
|||||||
BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params }
|
BareFunctionDecl { unsafety: bare_fn.unsafety, abi: bare_fn.abi, decl, generic_params }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This visitor is used to go through only the "top level" of a item and not enter any sub
|
/// Get DefId of of an item's user-visible parent.
|
||||||
/// item while looking for a given `Ident` which is stored into `item` if found.
|
///
|
||||||
struct OneLevelVisitor<'hir> {
|
/// "User-visible" should account for re-exporting and inlining, which is why this function isn't
|
||||||
|
/// just `tcx.parent(def_id)`. If the provided `path` has more than one path element, the `DefId`
|
||||||
|
/// of the second-to-last will be given.
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// use crate::foo::Bar;
|
||||||
|
/// ^^^ DefId of this item will be returned
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If the provided path has only one item, `tcx.parent(def_id)` will be returned instead.
|
||||||
|
fn get_path_parent_def_id(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
def_id: DefId,
|
||||||
|
path: &hir::UsePath<'_>,
|
||||||
|
) -> Option<DefId> {
|
||||||
|
if let [.., parent_segment, _] = &path.segments {
|
||||||
|
match parent_segment.res {
|
||||||
|
hir::def::Res::Def(_, parent_def_id) => Some(parent_def_id),
|
||||||
|
_ if parent_segment.ident.name == kw::Crate => {
|
||||||
|
// In case the "parent" is the crate, it'll give `Res::Err` so we need to
|
||||||
|
// circumvent it this way.
|
||||||
|
Some(tcx.parent(def_id))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If the path doesn't have a parent, then the parent is the current module.
|
||||||
|
Some(tcx.parent(def_id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This visitor is used to find an HIR Item based on its `use` path. This doesn't use the ordinary
|
||||||
|
/// name resolver because it does not walk all the way through a chain of re-exports.
|
||||||
|
pub(crate) struct OneLevelVisitor<'hir> {
|
||||||
map: rustc_middle::hir::map::Map<'hir>,
|
map: rustc_middle::hir::map::Map<'hir>,
|
||||||
item: Option<&'hir hir::Item<'hir>>,
|
pub(crate) item: Option<&'hir hir::Item<'hir>>,
|
||||||
looking_for: Ident,
|
looking_for: Ident,
|
||||||
target_def_id: LocalDefId,
|
target_def_id: LocalDefId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> OneLevelVisitor<'hir> {
|
impl<'hir> OneLevelVisitor<'hir> {
|
||||||
fn new(map: rustc_middle::hir::map::Map<'hir>, target_def_id: LocalDefId) -> Self {
|
pub(crate) fn new(map: rustc_middle::hir::map::Map<'hir>, target_def_id: LocalDefId) -> Self {
|
||||||
Self { map, item: None, looking_for: Ident::empty(), target_def_id }
|
Self { map, item: None, looking_for: Ident::empty(), target_def_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&mut self, looking_for: Ident) {
|
pub(crate) fn find_target(
|
||||||
self.looking_for = looking_for;
|
&mut self,
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
def_id: DefId,
|
||||||
|
path: &hir::UsePath<'_>,
|
||||||
|
) -> Option<&'hir hir::Item<'hir>> {
|
||||||
|
let parent_def_id = get_path_parent_def_id(tcx, def_id, path)?;
|
||||||
|
let parent = self.map.get_if_local(parent_def_id)?;
|
||||||
|
|
||||||
|
// We get the `Ident` we will be looking for into `item`.
|
||||||
|
self.looking_for = path.segments[path.segments.len() - 1].ident;
|
||||||
|
// We reset the `item`.
|
||||||
self.item = None;
|
self.item = None;
|
||||||
|
|
||||||
|
match parent {
|
||||||
|
hir::Node::Item(parent_item) => {
|
||||||
|
hir::intravisit::walk_item(self, parent_item);
|
||||||
|
}
|
||||||
|
hir::Node::Crate(m) => {
|
||||||
|
hir::intravisit::walk_mod(
|
||||||
|
self,
|
||||||
|
m,
|
||||||
|
tcx.local_def_id_to_hir_id(parent_def_id.as_local().unwrap()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
self.item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2129,41 +2187,7 @@ fn get_all_import_attributes<'hir>(
|
|||||||
add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
|
add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_id = if let [.., parent_segment, _] = &path.segments {
|
if let Some(i) = visitor.find_target(tcx, item.owner_id.def_id.to_def_id(), path) {
|
||||||
match parent_segment.res {
|
|
||||||
hir::def::Res::Def(_, def_id) => def_id,
|
|
||||||
_ if parent_segment.ident.name == kw::Crate => {
|
|
||||||
// In case the "parent" is the crate, it'll give `Res::Err` so we need to
|
|
||||||
// circumvent it this way.
|
|
||||||
tcx.parent(item.owner_id.def_id.to_def_id())
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the path doesn't have a parent, then the parent is the current module.
|
|
||||||
tcx.parent(item.owner_id.def_id.to_def_id())
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(parent) = hir_map.get_if_local(def_id) else { break };
|
|
||||||
|
|
||||||
// We get the `Ident` we will be looking for into `item`.
|
|
||||||
let looking_for = path.segments[path.segments.len() - 1].ident;
|
|
||||||
visitor.reset(looking_for);
|
|
||||||
|
|
||||||
match parent {
|
|
||||||
hir::Node::Item(parent_item) => {
|
|
||||||
hir::intravisit::walk_item(&mut visitor, parent_item);
|
|
||||||
}
|
|
||||||
hir::Node::Crate(m) => {
|
|
||||||
hir::intravisit::walk_mod(
|
|
||||||
&mut visitor,
|
|
||||||
m,
|
|
||||||
tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
if let Some(i) = visitor.item {
|
|
||||||
item = i;
|
item = i;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -647,11 +647,35 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
|||||||
</noscript>\
|
</noscript>\
|
||||||
<link rel=\"stylesheet\" \
|
<link rel=\"stylesheet\" \
|
||||||
href=\"{static_root_path}{settings_css}\">\
|
href=\"{static_root_path}{settings_css}\">\
|
||||||
<script defer src=\"{static_root_path}{settings_js}\"></script>",
|
<script defer src=\"{static_root_path}{settings_js}\"></script>\
|
||||||
|
<link rel=\"preload\" href=\"{static_root_path}{theme_light_css}\" \
|
||||||
|
as=\"style\">\
|
||||||
|
<link rel=\"preload\" href=\"{static_root_path}{theme_dark_css}\" \
|
||||||
|
as=\"style\">\
|
||||||
|
<link rel=\"preload\" href=\"{static_root_path}{theme_ayu_css}\" \
|
||||||
|
as=\"style\">",
|
||||||
static_root_path = page.get_static_root_path(),
|
static_root_path = page.get_static_root_path(),
|
||||||
settings_css = static_files::STATIC_FILES.settings_css,
|
settings_css = static_files::STATIC_FILES.settings_css,
|
||||||
settings_js = static_files::STATIC_FILES.settings_js,
|
settings_js = static_files::STATIC_FILES.settings_js,
|
||||||
)
|
theme_light_css = static_files::STATIC_FILES.theme_light_css,
|
||||||
|
theme_dark_css = static_files::STATIC_FILES.theme_dark_css,
|
||||||
|
theme_ayu_css = static_files::STATIC_FILES.theme_ayu_css,
|
||||||
|
);
|
||||||
|
// Pre-load all theme CSS files, so that switching feels seamless.
|
||||||
|
//
|
||||||
|
// When loading settings.html as a popover, the equivalent HTML is
|
||||||
|
// generated in main.js.
|
||||||
|
for file in &shared.style_files {
|
||||||
|
if let Ok(theme) = file.basename() {
|
||||||
|
write!(
|
||||||
|
buf,
|
||||||
|
"<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
|
||||||
|
as=\"style\">",
|
||||||
|
root_path = page.static_root_path.unwrap_or(""),
|
||||||
|
suffix = page.resource_suffix,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
&shared.style_files,
|
&shared.style_files,
|
||||||
);
|
);
|
||||||
|
@ -29,12 +29,12 @@ pub(crate) enum LinkFromSrc {
|
|||||||
|
|
||||||
/// This function will do at most two things:
|
/// This function will do at most two things:
|
||||||
///
|
///
|
||||||
/// 1. Generate a `span` correspondance map which links an item `span` to its definition `span`.
|
/// 1. Generate a `span` correspondence map which links an item `span` to its definition `span`.
|
||||||
/// 2. Collect the source code files.
|
/// 2. Collect the source code files.
|
||||||
///
|
///
|
||||||
/// It returns the `krate`, the source code files and the `span` correspondance map.
|
/// It returns the `krate`, the source code files and the `span` correspondence map.
|
||||||
///
|
///
|
||||||
/// Note about the `span` correspondance map: the keys are actually `(lo, hi)` of `span`s. We don't
|
/// Note about the `span` correspondence map: the keys are actually `(lo, hi)` of `span`s. We don't
|
||||||
/// need the `span` context later on, only their position, so instead of keep a whole `Span`, we
|
/// need the `span` context later on, only their position, so instead of keep a whole `Span`, we
|
||||||
/// only keep the `lo` and `hi`.
|
/// only keep the `lo` and `hi`.
|
||||||
pub(crate) fn collect_spans_and_sources(
|
pub(crate) fn collect_spans_and_sources(
|
||||||
|
@ -1,20 +1,9 @@
|
|||||||
// Local js definitions:
|
// Local js definitions:
|
||||||
/* global addClass, getSettingValue, hasClass, searchState */
|
/* global addClass, getSettingValue, hasClass, searchState */
|
||||||
/* global onEach, onEachLazy, removeClass */
|
/* global onEach, onEachLazy, removeClass, getVar */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Get a value from the rustdoc-vars div, which is used to convey data from
|
|
||||||
// Rust to the JS. If there is no such element, return null.
|
|
||||||
function getVar(name) {
|
|
||||||
const el = document.getElementById("rustdoc-vars");
|
|
||||||
if (el) {
|
|
||||||
return el.attributes["data-" + name].value;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
|
// Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
|
||||||
// for a resource under the root-path, with the resource-suffix.
|
// for a resource under the root-path, with the resource-suffix.
|
||||||
function resourcePath(basename, extension) {
|
function resourcePath(basename, extension) {
|
||||||
@ -187,6 +176,15 @@ function loadCss(cssUrl) {
|
|||||||
document.getElementsByTagName("head")[0].appendChild(link);
|
document.getElementsByTagName("head")[0].appendChild(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function preLoadCss(cssUrl) {
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload
|
||||||
|
const link = document.createElement("link");
|
||||||
|
link.href = cssUrl;
|
||||||
|
link.rel = "preload";
|
||||||
|
link.as = "style";
|
||||||
|
document.getElementsByTagName("head")[0].appendChild(link);
|
||||||
|
}
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
const isHelpPage = window.location.pathname.endsWith("/help.html");
|
const isHelpPage = window.location.pathname.endsWith("/help.html");
|
||||||
|
|
||||||
@ -207,6 +205,23 @@ function loadCss(cssUrl) {
|
|||||||
// hopefully be loaded when the JS will generate the settings content.
|
// hopefully be loaded when the JS will generate the settings content.
|
||||||
loadCss(getVar("static-root-path") + getVar("settings-css"));
|
loadCss(getVar("static-root-path") + getVar("settings-css"));
|
||||||
loadScript(getVar("static-root-path") + getVar("settings-js"));
|
loadScript(getVar("static-root-path") + getVar("settings-js"));
|
||||||
|
preLoadCss(getVar("static-root-path") + getVar("theme-light-css"));
|
||||||
|
preLoadCss(getVar("static-root-path") + getVar("theme-dark-css"));
|
||||||
|
preLoadCss(getVar("static-root-path") + getVar("theme-ayu-css"));
|
||||||
|
// Pre-load all theme CSS files, so that switching feels seamless.
|
||||||
|
//
|
||||||
|
// When loading settings.html as a standalone page, the equivalent HTML is
|
||||||
|
// generated in context.rs.
|
||||||
|
setTimeout(() => {
|
||||||
|
const themes = getVar("themes").split(",");
|
||||||
|
for (const theme of themes) {
|
||||||
|
// if there are no themes, do nothing
|
||||||
|
// "".split(",") == [""]
|
||||||
|
if (theme !== "") {
|
||||||
|
preLoadCss(getVar("root-path") + theme + ".css");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.searchState = {
|
window.searchState = {
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
const darkThemes = ["dark", "ayu"];
|
const darkThemes = ["dark", "ayu"];
|
||||||
window.currentTheme = document.getElementById("themeStyle");
|
window.currentTheme = document.getElementById("themeStyle");
|
||||||
window.mainTheme = document.getElementById("mainThemeStyle");
|
|
||||||
|
|
||||||
// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
||||||
// If you update this line, then you also need to update the media query with the same
|
// If you update this line, then you also need to update the media query with the same
|
||||||
@ -44,8 +43,6 @@ function getSettingValue(settingName) {
|
|||||||
|
|
||||||
const localStoredTheme = getSettingValue("theme");
|
const localStoredTheme = getSettingValue("theme");
|
||||||
|
|
||||||
const savedHref = [];
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function hasClass(elem, className) {
|
function hasClass(elem, className) {
|
||||||
return elem && elem.classList && elem.classList.contains(className);
|
return elem && elem.classList && elem.classList.contains(className);
|
||||||
@ -102,6 +99,7 @@ function onEach(arr, func, reversed) {
|
|||||||
* @param {function(?)} func - The callback
|
* @param {function(?)} func - The callback
|
||||||
* @param {boolean} [reversed] - Whether to iterate in reverse
|
* @param {boolean} [reversed] - Whether to iterate in reverse
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
function onEachLazy(lazyArray, func, reversed) {
|
function onEachLazy(lazyArray, func, reversed) {
|
||||||
return onEach(
|
return onEach(
|
||||||
Array.prototype.slice.call(lazyArray),
|
Array.prototype.slice.call(lazyArray),
|
||||||
@ -125,30 +123,37 @@ function getCurrentValue(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) {
|
// Get a value from the rustdoc-vars div, which is used to convey data from
|
||||||
|
// Rust to the JS. If there is no such element, return null.
|
||||||
|
const getVar = (function getVar(name) {
|
||||||
|
const el = document.getElementById("rustdoc-vars");
|
||||||
|
if (el) {
|
||||||
|
return el.attributes["data-" + name].value;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function switchTheme(newThemeName, saveTheme) {
|
||||||
// If this new value comes from a system setting or from the previously
|
// If this new value comes from a system setting or from the previously
|
||||||
// saved theme, no need to save it.
|
// saved theme, no need to save it.
|
||||||
if (saveTheme) {
|
if (saveTheme) {
|
||||||
updateLocalStorage("theme", newThemeName);
|
updateLocalStorage("theme", newThemeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (savedHref.length === 0) {
|
let newHref;
|
||||||
onEachLazy(document.getElementsByTagName("link"), el => {
|
|
||||||
savedHref.push(el.href);
|
if (newThemeName === "light" || newThemeName === "dark" || newThemeName === "ayu") {
|
||||||
});
|
newHref = getVar("static-root-path") + getVar("theme-" + newThemeName + "-css");
|
||||||
|
} else {
|
||||||
|
newHref = getVar("root-path") + newThemeName + getVar("resource-suffix") + ".css";
|
||||||
}
|
}
|
||||||
const newHref = savedHref.find(url => {
|
|
||||||
const m = url.match(/static\.files\/(.*)-[a-f0-9]{16}\.css$/);
|
if (!window.currentTheme) {
|
||||||
if (m && m[1] === newThemeName) {
|
document.write(`<link rel="stylesheet" id="themeStyle" href="${newHref}">`);
|
||||||
return true;
|
window.currentTheme = document.getElementById("themeStyle");
|
||||||
}
|
} else if (newHref !== window.currentTheme.href) {
|
||||||
const m2 = url.match(/\/([^/]*)\.css$/);
|
window.currentTheme.href = newHref;
|
||||||
if (m2 && m2[1].startsWith(newThemeName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (newHref && newHref !== styleElem.href) {
|
|
||||||
styleElem.href = newHref;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +169,7 @@ const updateTheme = (function() {
|
|||||||
*/
|
*/
|
||||||
function updateTheme() {
|
function updateTheme() {
|
||||||
const use = (theme, saveTheme) => {
|
const use = (theme, saveTheme) => {
|
||||||
switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme);
|
switchTheme(theme, saveTheme);
|
||||||
};
|
};
|
||||||
|
|
||||||
// maybe the user has disabled the setting in the meantime!
|
// maybe the user has disabled the setting in the meantime!
|
||||||
|
@ -17,12 +17,6 @@
|
|||||||
<link rel="stylesheet" {#+ #}
|
<link rel="stylesheet" {#+ #}
|
||||||
href="{{static_root_path|safe}}{{files.rustdoc_css}}" {#+ #}
|
href="{{static_root_path|safe}}{{files.rustdoc_css}}" {#+ #}
|
||||||
id="mainThemeStyle"> {# #}
|
id="mainThemeStyle"> {# #}
|
||||||
<link rel="stylesheet" id="themeStyle" href="{{static_root_path|safe}}{{files.theme_light_css}}"> {# #}
|
|
||||||
<link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {# #}
|
|
||||||
<link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_ayu_css}}"> {# #}
|
|
||||||
{% for theme in themes %}
|
|
||||||
<link rel="stylesheet" disabled href="{{page.root_path|safe}}{{theme}}{{page.resource_suffix}}.css"> {# #}
|
|
||||||
{% endfor %}
|
|
||||||
{% if !layout.default_settings.is_empty() %}
|
{% if !layout.default_settings.is_empty() %}
|
||||||
<script id="default-settings" {#+ #}
|
<script id="default-settings" {#+ #}
|
||||||
{%~ for (k, v) in layout.default_settings ~%}
|
{%~ for (k, v) in layout.default_settings ~%}
|
||||||
@ -30,6 +24,21 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
></script> {# #}
|
></script> {# #}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div id="rustdoc-vars" {#+ #}
|
||||||
|
data-root-path="{{page.root_path|safe}}" {#+ #}
|
||||||
|
data-static-root-path="{{static_root_path|safe}}" {#+ #}
|
||||||
|
data-current-crate="{{layout.krate}}" {#+ #}
|
||||||
|
data-themes="{{themes|join(",") }}" {#+ #}
|
||||||
|
data-resource-suffix="{{page.resource_suffix}}" {#+ #}
|
||||||
|
data-rustdoc-version="{{rustdoc_version}}" {#+ #}
|
||||||
|
data-search-js="{{files.search_js}}" {#+ #}
|
||||||
|
data-settings-js="{{files.settings_js}}" {#+ #}
|
||||||
|
data-settings-css="{{files.settings_css}}" {#+ #}
|
||||||
|
data-theme-light-css="{{files.theme_light_css}}" {#+ #}
|
||||||
|
data-theme-dark-css="{{files.theme_dark_css}}" {#+ #}
|
||||||
|
data-theme-ayu-css="{{files.theme_ayu_css}}" {#+ #}
|
||||||
|
> {# #}
|
||||||
|
</div> {# #}
|
||||||
<script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {# #}
|
<script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {# #}
|
||||||
{% if page.css_class.contains("crate") %}
|
{% if page.css_class.contains("crate") %}
|
||||||
<script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {# #}
|
<script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {# #}
|
||||||
@ -44,6 +53,12 @@
|
|||||||
<script defer src="{{static_root_path|safe}}{{files.scrape_examples_js}}"></script> {# #}
|
<script defer src="{{static_root_path|safe}}{{files.scrape_examples_js}}"></script> {# #}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<noscript> {# #}
|
<noscript> {# #}
|
||||||
|
<link rel="stylesheet" {#+ #}
|
||||||
|
media="(prefers-color-scheme:light)" {#+ #}
|
||||||
|
href="{{static_root_path|safe}}{{files.theme_light_css}}"> {# #}
|
||||||
|
<link rel="stylesheet" {#+ #}
|
||||||
|
media="(prefers-color-scheme:dark)" {#+ #}
|
||||||
|
href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {# #}
|
||||||
<link rel="stylesheet" {#+ #}
|
<link rel="stylesheet" {#+ #}
|
||||||
href="{{static_root_path|safe}}{{files.noscript_css}}"> {# #}
|
href="{{static_root_path|safe}}{{files.noscript_css}}"> {# #}
|
||||||
</noscript> {# #}
|
</noscript> {# #}
|
||||||
@ -132,17 +147,5 @@
|
|||||||
{% if page.css_class != "source" %}</div>{% endif %}
|
{% if page.css_class != "source" %}</div>{% endif %}
|
||||||
</main> {# #}
|
</main> {# #}
|
||||||
{{ layout.external_html.after_content|safe }}
|
{{ layout.external_html.after_content|safe }}
|
||||||
<div id="rustdoc-vars" {#+ #}
|
|
||||||
data-root-path="{{page.root_path|safe}}" {#+ #}
|
|
||||||
data-static-root-path="{{static_root_path|safe}}" {#+ #}
|
|
||||||
data-current-crate="{{layout.krate}}" {#+ #}
|
|
||||||
data-themes="{{themes|join(",") }}" {#+ #}
|
|
||||||
data-resource-suffix="{{page.resource_suffix}}" {#+ #}
|
|
||||||
data-rustdoc-version="{{rustdoc_version}}" {#+ #}
|
|
||||||
data-search-js="{{files.search_js}}" {#+ #}
|
|
||||||
data-settings-js="{{files.settings_js}}" {#+ #}
|
|
||||||
data-settings-css="{{files.settings_css}}" {#+ #}
|
|
||||||
> {# #}
|
|
||||||
</div> {# #}
|
|
||||||
</body> {# #}
|
</body> {# #}
|
||||||
</html> {# #}
|
</html> {# #}
|
||||||
|
@ -15,7 +15,7 @@ use rustc_span::Span;
|
|||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crate::clean::{cfg::Cfg, AttributesExt, NestedAttributesExt};
|
use crate::clean::{cfg::Cfg, AttributesExt, NestedAttributesExt, OneLevelVisitor};
|
||||||
use crate::core;
|
use crate::core;
|
||||||
|
|
||||||
/// This module is used to store stuff from Rust's AST in a more convenient
|
/// This module is used to store stuff from Rust's AST in a more convenient
|
||||||
@ -220,6 +220,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
renamed: Option<Symbol>,
|
renamed: Option<Symbol>,
|
||||||
glob: bool,
|
glob: bool,
|
||||||
please_inline: bool,
|
please_inline: bool,
|
||||||
|
path: &hir::UsePath<'_>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!("maybe_inline_local res: {:?}", res);
|
debug!("maybe_inline_local res: {:?}", res);
|
||||||
|
|
||||||
@ -263,6 +264,22 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !please_inline &&
|
||||||
|
let mut visitor = OneLevelVisitor::new(self.cx.tcx.hir(), res_did) &&
|
||||||
|
let Some(item) = visitor.find_target(self.cx.tcx, def_id.to_def_id(), path) &&
|
||||||
|
let item_def_id = item.owner_id.def_id &&
|
||||||
|
item_def_id != def_id &&
|
||||||
|
self
|
||||||
|
.cx
|
||||||
|
.cache
|
||||||
|
.effective_visibilities
|
||||||
|
.is_directly_public(self.cx.tcx, item_def_id.to_def_id()) &&
|
||||||
|
!inherits_doc_hidden(self.cx.tcx, item_def_id)
|
||||||
|
{
|
||||||
|
// The imported item is public and not `doc(hidden)` so no need to inline it.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let ret = match tcx.hir().get_by_def_id(res_did) {
|
let ret = match tcx.hir().get_by_def_id(res_did) {
|
||||||
Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
|
Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
|
||||||
let prev = mem::replace(&mut self.inlining, true);
|
let prev = mem::replace(&mut self.inlining, true);
|
||||||
@ -361,6 +378,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
ident,
|
ident,
|
||||||
is_glob,
|
is_glob,
|
||||||
please_inline,
|
please_inline,
|
||||||
|
path,
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,8 @@ const EXCEPTION_PATHS: &[&str] = &[
|
|||||||
"library/std/src/panic.rs", // fuchsia-specific panic backtrace handling
|
"library/std/src/panic.rs", // fuchsia-specific panic backtrace handling
|
||||||
"library/std/src/personality.rs",
|
"library/std/src/personality.rs",
|
||||||
"library/std/src/personality/",
|
"library/std/src/personality/",
|
||||||
|
"library/std/src/thread/mod.rs",
|
||||||
|
"library/std/src/thread/local.rs",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn check(path: &Path, bad: &mut bool) {
|
pub fn check(path: &Path, bad: &mut bool) {
|
||||||
@ -128,6 +130,7 @@ fn check_cfgs(
|
|||||||
|| cfg.contains("target_env")
|
|| cfg.contains("target_env")
|
||||||
|| cfg.contains("target_abi")
|
|| cfg.contains("target_abi")
|
||||||
|| cfg.contains("target_vendor")
|
|| cfg.contains("target_vendor")
|
||||||
|
|| cfg.contains("target_family")
|
||||||
|| cfg.contains("unix")
|
|| cfg.contains("unix")
|
||||||
|| cfg.contains("windows");
|
|| cfg.contains("windows");
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// @has test.css
|
// @has test.css
|
||||||
// @has foo/struct.Foo.html
|
// @has foo/struct.Foo.html
|
||||||
// @has - '//link[@rel="stylesheet"]/@href' '../test.css'
|
// @has - '//*[@id="rustdoc-vars"]/@data-themes' 'test'
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
@ -8,24 +8,24 @@ focus: ".scraped-example-list > .scraped-example .next"
|
|||||||
press-key: "Enter"
|
press-key: "Enter"
|
||||||
assert-property-false: (".scraped-example-list > .scraped-example pre", {
|
assert-property-false: (".scraped-example-list > .scraped-example pre", {
|
||||||
"scrollTop": |initialScrollTop|
|
"scrollTop": |initialScrollTop|
|
||||||
})
|
}, NEAR)
|
||||||
focus: ".scraped-example-list > .scraped-example .prev"
|
focus: ".scraped-example-list > .scraped-example .prev"
|
||||||
press-key: "Enter"
|
press-key: "Enter"
|
||||||
assert-property: (".scraped-example-list > .scraped-example pre", {
|
assert-property: (".scraped-example-list > .scraped-example pre", {
|
||||||
"scrollTop": |initialScrollTop|
|
"scrollTop": |initialScrollTop|
|
||||||
})
|
}, NEAR)
|
||||||
|
|
||||||
// The expand button increases the scrollHeight of the minimized code viewport
|
// The expand button increases the scrollHeight of the minimized code viewport
|
||||||
store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
|
store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
|
||||||
assert-property-false: (".scraped-example-list > .scraped-example pre", {
|
assert-property-false: (".scraped-example-list > .scraped-example pre", {
|
||||||
"scrollHeight": |smallOffsetHeight|
|
"scrollHeight": |smallOffsetHeight|
|
||||||
})
|
}, NEAR)
|
||||||
focus: ".scraped-example-list > .scraped-example .expand"
|
focus: ".scraped-example-list > .scraped-example .expand"
|
||||||
press-key: "Enter"
|
press-key: "Enter"
|
||||||
assert-property-false: (".scraped-example-list > .scraped-example pre", {
|
assert-property-false: (".scraped-example-list > .scraped-example pre", {
|
||||||
"offsetHeight": |smallOffsetHeight|
|
"offsetHeight": |smallOffsetHeight|
|
||||||
})
|
}, NEAR)
|
||||||
store-property: (fullOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
|
store-property: (fullOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
|
||||||
assert-property: (".scraped-example-list > .scraped-example pre", {
|
assert-property: (".scraped-example-list > .scraped-example pre", {
|
||||||
"scrollHeight": |fullOffsetHeight|
|
"scrollHeight": |fullOffsetHeight|
|
||||||
})
|
}, NEAR)
|
||||||
|
29
tests/rustdoc/issue-108679-reexport-of-reexport.rs
Normal file
29
tests/rustdoc/issue-108679-reexport-of-reexport.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// This test ensures that the `struct.B.html` only exists in `a`:
|
||||||
|
// since `a::B` is public (and inlined too), `self::a::B` doesn't
|
||||||
|
// need to be inlined as well.
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
pub mod a {
|
||||||
|
// @has 'foo/a/index.html'
|
||||||
|
// Should only contain "Structs".
|
||||||
|
// @count - '//*[@id="main-content"]//*[@class="item-table"]' 1
|
||||||
|
// @has - '//*[@id="structs"]' 'Structs'
|
||||||
|
// @has - '//*[@id="main-content"]//a[@href="struct.A.html"]' 'A'
|
||||||
|
// @has - '//*[@id="main-content"]//a[@href="struct.B.html"]' 'B'
|
||||||
|
mod b {
|
||||||
|
pub struct B;
|
||||||
|
}
|
||||||
|
pub use self::b::B;
|
||||||
|
pub struct A;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has 'foo/index.html'
|
||||||
|
// @!has - '//*[@id="structs"]' 'Structs'
|
||||||
|
// @has - '//*[@id="reexports"]' 'Re-exports'
|
||||||
|
// @has - '//*[@id="modules"]' 'Modules'
|
||||||
|
// @has - '//*[@id="main-content"]//*[@id="reexport.A"]' 'pub use self::a::A;'
|
||||||
|
// @has - '//*[@id="main-content"]//*[@id="reexport.B"]' 'pub use self::a::B;'
|
||||||
|
// Should only contain "Modules" and "Re-exports".
|
||||||
|
// @count - '//*[@id="main-content"]//*[@class="item-table"]' 2
|
||||||
|
pub use self::a::{A, B};
|
2
tests/ui/parser/integer-literal-start-ident.rs
Normal file
2
tests/ui/parser/integer-literal-start-ident.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fn 1main() {}
|
||||||
|
//~^ ERROR expected identifier, found `1main`
|
10
tests/ui/parser/integer-literal-start-ident.stderr
Normal file
10
tests/ui/parser/integer-literal-start-ident.stderr
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
error: expected identifier, found `1main`
|
||||||
|
--> $DIR/integer-literal-start-ident.rs:1:4
|
||||||
|
|
|
||||||
|
LL | fn 1main() {}
|
||||||
|
| ^^^^^ expected identifier
|
||||||
|
|
|
||||||
|
= help: identifiers cannot start with a number
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -4,12 +4,12 @@ fn test() {
|
|||||||
|
|
||||||
fn test_2() {
|
fn test_2() {
|
||||||
let 1x = 123;
|
let 1x = 123;
|
||||||
//~^ ERROR expected identifier, found number literal
|
//~^ ERROR expected identifier, found `1x`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_3() {
|
fn test_3() {
|
||||||
let 2x: i32 = 123;
|
let 2x: i32 = 123;
|
||||||
//~^ ERROR expected identifier, found number literal
|
//~^ ERROR expected identifier, found `2x`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_4() {
|
fn test_4() {
|
||||||
@ -20,7 +20,7 @@ fn test_4() {
|
|||||||
|
|
||||||
fn test_5() {
|
fn test_5() {
|
||||||
let 23name = 123;
|
let 23name = 123;
|
||||||
//~^ ERROR expected identifier, found number literal
|
//~^ ERROR expected identifier, found `23name`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,20 +1,26 @@
|
|||||||
error: expected identifier, found number literal
|
error: expected identifier, found `1x`
|
||||||
--> $DIR/issue-104088.rs:6:9
|
--> $DIR/issue-104088.rs:6:9
|
||||||
|
|
|
|
||||||
LL | let 1x = 123;
|
LL | let 1x = 123;
|
||||||
| ^^ identifiers cannot start with a number
|
| ^^ expected identifier
|
||||||
|
|
|
||||||
|
= help: identifiers cannot start with a number
|
||||||
|
|
||||||
error: expected identifier, found number literal
|
error: expected identifier, found `2x`
|
||||||
--> $DIR/issue-104088.rs:11:9
|
--> $DIR/issue-104088.rs:11:9
|
||||||
|
|
|
|
||||||
LL | let 2x: i32 = 123;
|
LL | let 2x: i32 = 123;
|
||||||
| ^^ identifiers cannot start with a number
|
| ^^ expected identifier
|
||||||
|
|
|
||||||
|
= help: identifiers cannot start with a number
|
||||||
|
|
||||||
error: expected identifier, found number literal
|
error: expected identifier, found `23name`
|
||||||
--> $DIR/issue-104088.rs:22:9
|
--> $DIR/issue-104088.rs:22:9
|
||||||
|
|
|
|
||||||
LL | let 23name = 123;
|
LL | let 23name = 123;
|
||||||
| ^^^^^^ identifiers cannot start with a number
|
| ^^^^^^ expected identifier
|
||||||
|
|
|
||||||
|
= help: identifiers cannot start with a number
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-104088.rs:16:12
|
--> $DIR/issue-104088.rs:16:12
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
trait Foo
|
||||||
|
where
|
||||||
|
for<'a> &'a Self: Bar,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for () {}
|
||||||
|
|
||||||
|
trait Bar {}
|
||||||
|
|
||||||
|
impl Bar for &() {}
|
||||||
|
|
||||||
|
fn foo<T: Foo>() {}
|
||||||
|
//~^ ERROR the trait bound `for<'a> &'a T: Bar` is not satisfied
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,22 @@
|
|||||||
|
error[E0277]: the trait bound `for<'a> &'a T: Bar` is not satisfied
|
||||||
|
--> $DIR/correct-binder-for-arbitrary-bound-sugg.rs:13:11
|
||||||
|
|
|
||||||
|
LL | fn foo<T: Foo>() {}
|
||||||
|
| ^^^ the trait `for<'a> Bar` is not implemented for `&'a T`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Foo`
|
||||||
|
--> $DIR/correct-binder-for-arbitrary-bound-sugg.rs:3:23
|
||||||
|
|
|
||||||
|
LL | trait Foo
|
||||||
|
| --- required by a bound in this trait
|
||||||
|
LL | where
|
||||||
|
LL | for<'a> &'a Self: Bar,
|
||||||
|
| ^^^ required by this bound in `Foo`
|
||||||
|
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||||
|
|
|
||||||
|
LL | fn foo<T: Foo>() where for<'a> &'a T: Bar {}
|
||||||
|
| ++++++++++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
@ -451,6 +451,10 @@ cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
|
|||||||
message = "`rustc_macros::diagnostics` was changed"
|
message = "`rustc_macros::diagnostics` was changed"
|
||||||
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
|
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
|
||||||
|
|
||||||
|
[mentions."compiler/rustc_smir"]
|
||||||
|
message = "This PR changes Stable MIR"
|
||||||
|
cc = ["@oli-obk", "@celinval"]
|
||||||
|
|
||||||
[mentions."compiler/rustc_target/src/spec"]
|
[mentions."compiler/rustc_target/src/spec"]
|
||||||
message = """
|
message = """
|
||||||
These commits modify **compiler targets**.
|
These commits modify **compiler targets**.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user