aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock27
-rw-r--r--crates/ra_assists/src/handlers/add_explicit_type.rs4
-rw-r--r--crates/ra_assists/src/handlers/add_impl.rs2
-rw-r--r--crates/ra_assists/src/handlers/add_new.rs3
-rw-r--r--crates/ra_assists/src/handlers/inline_local_variable.rs2
-rw-r--r--crates/ra_assists/src/handlers/introduce_variable.rs2
-rw-r--r--crates/ra_assists/src/handlers/merge_imports.rs4
-rw-r--r--crates/ra_assists/src/handlers/move_bounds.rs3
-rw-r--r--crates/ra_hir/src/source_analyzer.rs2
-rw-r--r--crates/ra_hir_def/src/adt.rs57
-rw-r--r--crates/ra_hir_def/src/attr.rs5
-rw-r--r--crates/ra_hir_def/src/body.rs6
-rw-r--r--crates/ra_hir_def/src/body/lower.rs71
-rw-r--r--crates/ra_hir_def/src/data.rs18
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs2
-rw-r--r--crates/ra_hir_def/src/expr.rs33
-rw-r--r--crates/ra_hir_def/src/lang_item.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs2
-rw-r--r--crates/ra_hir_def/src/type_ref.rs4
-rw-r--r--crates/ra_hir_expand/src/ast_id_map.rs2
-rw-r--r--crates/ra_hir_ty/Cargo.toml2
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs31
-rw-r--r--crates/ra_hir_ty/src/display.rs26
-rw-r--r--crates/ra_hir_ty/src/expr.rs114
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs2
-rw-r--r--crates/ra_hir_ty/src/tests.rs106
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs31
-rw-r--r--crates/ra_hir_ty/src/traits.rs13
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs81
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs231
-rw-r--r--crates/ra_ide/src/completion/complete_fn_param.rs30
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs4
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs4
-rw-r--r--crates/ra_ide/src/inlay_hints.rs52
-rw-r--r--crates/ra_ide/src/references.rs2
-rw-r--r--crates/ra_ide/src/syntax_tree.rs8
-rw-r--r--crates/ra_ide/src/typing.rs2
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs36
-rw-r--r--crates/ra_mbe/src/tests.rs20
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs3
-rw-r--r--crates/ra_parser/src/grammar/types.rs15
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs328
-rw-r--r--crates/ra_prof/src/lib.rs15
-rw-r--r--crates/ra_syntax/src/ast.rs42
-rw-r--r--crates/ra_syntax/src/ast/edit.rs17
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs32
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs90
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs559
-rw-r--r--crates/ra_syntax/src/ast/generated/tokens.rs2741
-rw-r--r--crates/ra_syntax/src/ast/traits.rs41
-rw-r--r--crates/ra_syntax/src/parsing/lexer.rs77
-rw-r--r--crates/ra_syntax/src/ptr.rs17
-rw-r--r--crates/ra_syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.txt2
-rw-r--r--crates/ra_syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.txt2
-rw-r--r--crates/ra_syntax/test_data/lexer/ok/0005_symbols.txt6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0002_duplicate_shebang.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0004_use_path_bad_segment.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0007_stray_curly_in_file.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0008_item_block_recovery.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0009_broken_struct_type_parameter.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0010_unsafe_lambda_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0011_extern_struct.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0012_broken_lambda.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/err/0013_invalid_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0016_missing_semi.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0017_incomplete_binexpr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0019_let_recover.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/err/0022_bad_exprs.rast24
-rw-r--r--crates/ra_syntax/test_data/parser/err/0023_mismatched_paren.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0024_many_type_parens.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/err/0025_nope.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0035_use_recover.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0036_partial_use.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0038_endless_inclusive_range.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0008_pub_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0001_trait_item_list.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rast34
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0007_type_param_bounds.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.rast16
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0009_loop_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0014_never_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0015_continue_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0017_array_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0019_unary_expr.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0020_use_star.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0021_impl_item_list.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0022_crate_visibility.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0023_placeholder_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0024_slice_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0025_slice_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0027_ref_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0028_impl_trait_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0029_cast_expr.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0033_reference_type;.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0034_break_expr.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0037_qual_paths.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0038_full_range_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0042_call_expr.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0043_use_alias.rast30
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0050_fn_decl.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0051_unit_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0052_path_type.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0053_path_expr.rast16
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0056_where_clause.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0058_range_pat.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0060_extern_crate.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0062_mod_contents.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0063_impl_def_neg.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0067_crate_path.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0072_return_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0073_type_item_type_params.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0075_block.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0077_try_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0078_type_item.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0084_paren_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0085_expr_literals.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0090_type_param_default.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0093_index_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0100_for_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0103_array_expr.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0106_lambda_expr.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0107_method_call_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0108_tuple_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0110_use_path.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast28
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0117_macro_call_type.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rast18
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_try_block_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0131_existential_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0132_box_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0142_for_range_from.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast82
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0150_array_attrs.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0151_trait_alias.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0006_inner_attributes.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0007_extern_crate.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0008_mod_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0009_use_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0010_use_path_segments.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0012_visibility.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0014_use_tree.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0015_use_tree.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.rast28
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0020_type_param_bounds.rast24
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0023_static_items.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0024_const_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0028_operator_binding_power.rast22
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0029_range_forms.rast36
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0030_string_suffixes.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0030_traits.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0031_extern.rast120
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0032_where_for.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0033_label_break.rast16
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0034_crate_path_in_call.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast432
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0036_fully_qualified.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0041_raw_keywords.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0042_ufcs_call_list.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0044_let_attrs.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0046_extern_inner_attributes.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0048_compound_assignment.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0049_async_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0050_async_block_as_argument.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0052_for_range_block.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0057_loop_in_call.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0060_as_range.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0061_match_full_range.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rast12
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs4
-rw-r--r--crates/rust-analyzer/src/world.rs4
-rw-r--r--crates/stdx/src/lib.rs16
-rw-r--r--crates/test_utils/src/lib.rs2
-rw-r--r--xtask/src/ast_src.rs425
-rw-r--r--xtask/src/codegen/gen_syntax.rs270
255 files changed, 2629 insertions, 5124 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f695a7f2c..975c1aef8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -614,9 +614,9 @@ checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
614 614
615[[package]] 615[[package]]
616name = "lock_api" 616name = "lock_api"
617version = "0.3.3" 617version = "0.3.4"
618source = "registry+https://github.com/rust-lang/crates.io-index" 618source = "registry+https://github.com/rust-lang/crates.io-index"
619checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" 619checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
620dependencies = [ 620dependencies = [
621 "scopeguard", 621 "scopeguard",
622] 622]
@@ -779,9 +779,9 @@ checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
779 779
780[[package]] 780[[package]]
781name = "parking_lot" 781name = "parking_lot"
782version = "0.10.0" 782version = "0.10.1"
783source = "registry+https://github.com/rust-lang/crates.io-index" 783source = "registry+https://github.com/rust-lang/crates.io-index"
784checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" 784checksum = "6fdfcb5f20930a79e326f7ec992a9fdb5b7bd809254b1e735bdd5a99f78bee0d"
785dependencies = [ 785dependencies = [
786 "lock_api", 786 "lock_api",
787 "parking_lot_core", 787 "parking_lot_core",
@@ -789,9 +789,9 @@ dependencies = [
789 789
790[[package]] 790[[package]]
791name = "parking_lot_core" 791name = "parking_lot_core"
792version = "0.7.0" 792version = "0.7.1"
793source = "registry+https://github.com/rust-lang/crates.io-index" 793source = "registry+https://github.com/rust-lang/crates.io-index"
794checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" 794checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
795dependencies = [ 795dependencies = [
796 "cfg-if", 796 "cfg-if",
797 "cloudabi", 797 "cloudabi",
@@ -1021,6 +1021,7 @@ dependencies = [
1021 "ra_prof", 1021 "ra_prof",
1022 "ra_syntax", 1022 "ra_syntax",
1023 "rustc-hash", 1023 "rustc-hash",
1024 "scoped-tls",
1024 "smallvec", 1025 "smallvec",
1025 "stdx", 1026 "stdx",
1026 "test_utils", 1027 "test_utils",
@@ -1420,6 +1421,12 @@ dependencies = [
1420] 1421]
1421 1422
1422[[package]] 1423[[package]]
1424name = "scoped-tls"
1425version = "1.0.0"
1426source = "registry+https://github.com/rust-lang/crates.io-index"
1427checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
1428
1429[[package]]
1423name = "scopeguard" 1430name = "scopeguard"
1424version = "1.1.0" 1431version = "1.1.0"
1425source = "registry+https://github.com/rust-lang/crates.io-index" 1432source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1523,9 +1530,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1523 1530
1524[[package]] 1531[[package]]
1525name = "smallvec" 1532name = "smallvec"
1526version = "1.2.0" 1533version = "1.3.0"
1527source = "registry+https://github.com/rust-lang/crates.io-index" 1534source = "registry+https://github.com/rust-lang/crates.io-index"
1528checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" 1535checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
1529 1536
1530[[package]] 1537[[package]]
1531name = "smol_str" 1538name = "smol_str"
@@ -1573,9 +1580,9 @@ dependencies = [
1573 1580
1574[[package]] 1581[[package]]
1575name = "termios" 1582name = "termios"
1576version = "0.3.1" 1583version = "0.3.2"
1577source = "registry+https://github.com/rust-lang/crates.io-index" 1584source = "registry+https://github.com/rust-lang/crates.io-index"
1578checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" 1585checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2"
1579dependencies = [ 1586dependencies = [
1580 "libc", 1587 "libc",
1581] 1588]
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs
index e7dcfb44e..d86d804b2 100644
--- a/crates/ra_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ra_assists/src/handlers/add_explicit_type.rs
@@ -1,6 +1,6 @@
1use hir::HirDisplay; 1use hir::HirDisplay;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode, AstToken, LetStmt, NameOwner, TypeAscriptionOwner}, 3 ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner},
4 TextRange, 4 TextRange,
5}; 5};
6 6
@@ -35,7 +35,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
35 let name = pat.name()?; 35 let name = pat.name()?;
36 let name_range = name.syntax().text_range(); 36 let name_range = name.syntax().text_range();
37 let stmt_range = stmt.syntax().text_range(); 37 let stmt_range = stmt.syntax().text_range();
38 let eq_range = stmt.eq_token()?.syntax().text_range(); 38 let eq_range = stmt.eq_token()?.text_range();
39 // Assist should only be applicable if cursor is between 'let' and '=' 39 // Assist should only be applicable if cursor is between 'let' and '='
40 let let_range = TextRange::from_to(stmt_range.start(), eq_range.start()); 40 let let_range = TextRange::from_to(stmt_range.start(), eq_range.start());
41 let cursor_in_range = ctx.frange.range.is_subrange(&let_range); 41 let cursor_in_range = ctx.frange.range.is_subrange(&let_range);
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs
index 26dfed237..6622eadb2 100644
--- a/crates/ra_assists/src/handlers/add_impl.rs
+++ b/crates/ra_assists/src/handlers/add_impl.rs
@@ -1,5 +1,5 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner}, 2 ast::{self, AstNode, NameOwner, TypeParamsOwner},
3 TextUnit, 3 TextUnit,
4}; 4};
5use stdx::{format_to, SepBy}; 5use stdx::{format_to, SepBy};
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs
index 30360af94..240b19fa3 100644
--- a/crates/ra_assists/src/handlers/add_new.rs
+++ b/crates/ra_assists/src/handlers/add_new.rs
@@ -1,8 +1,7 @@
1use hir::Adt; 1use hir::Adt;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{ 3 ast::{
4 self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, 4 self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
5 VisibilityOwner,
6 }, 5 },
7 TextUnit, T, 6 TextUnit, T,
8}; 7};
diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs
index b9eb09676..c4fb425b0 100644
--- a/crates/ra_assists/src/handlers/inline_local_variable.rs
+++ b/crates/ra_assists/src/handlers/inline_local_variable.rs
@@ -29,7 +29,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
29 ast::Pat::BindPat(pat) => pat, 29 ast::Pat::BindPat(pat) => pat,
30 _ => return None, 30 _ => return None,
31 }; 31 };
32 if bind_pat.mut_kw_token().is_some() { 32 if bind_pat.mut_token().is_some() {
33 tested_by!(test_not_inline_mut_variable); 33 tested_by!(test_not_inline_mut_variable);
34 return None; 34 return None;
35 } 35 }
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs
index ab6bdf6bb..8d0f7e922 100644
--- a/crates/ra_assists/src/handlers/introduce_variable.rs
+++ b/crates/ra_assists/src/handlers/introduce_variable.rs
@@ -61,7 +61,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> {
61 }; 61 };
62 if is_full_stmt { 62 if is_full_stmt {
63 tested_by!(test_introduce_var_expr_stmt); 63 tested_by!(test_introduce_var_expr_stmt);
64 if full_stmt.unwrap().semi_token().is_none() { 64 if full_stmt.unwrap().semicolon_token().is_none() {
65 buf.push_str(";"); 65 buf.push_str(";");
66 } 66 }
67 edit.replace(expr.syntax().text_range(), buf); 67 edit.replace(expr.syntax().text_range(), buf);
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs
index 936d50ab4..0958f52f1 100644
--- a/crates/ra_assists/src/handlers/merge_imports.rs
+++ b/crates/ra_assists/src/handlers/merge_imports.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{neighbor, SyntaxRewriter}, 4 algo::{neighbor, SyntaxRewriter},
5 ast::{self, edit::AstNodeEdit, make}, 5 ast::{self, edit::AstNodeEdit, make},
6 AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T, 6 AstNode, Direction, InsertPosition, SyntaxElement, T,
7}; 7};
8 8
9use crate::{Assist, AssistCtx, AssistId}; 9use crate::{Assist, AssistCtx, AssistId};
@@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre
82 .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']), 82 .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']),
83 ); 83 );
84 let use_tree_list = lhs.use_tree_list()?; 84 let use_tree_list = lhs.use_tree_list()?;
85 let pos = InsertPosition::Before(use_tree_list.r_curly_token()?.syntax().clone().into()); 85 let pos = InsertPosition::Before(use_tree_list.r_curly_token()?.into());
86 let use_tree_list = use_tree_list.insert_children(pos, to_insert); 86 let use_tree_list = use_tree_list.insert_children(pos, to_insert);
87 Some(lhs.with_use_tree_list(use_tree_list)) 87 Some(lhs.with_use_tree_list(use_tree_list))
88} 88}
diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs
index 93f26f51a..0f26884dc 100644
--- a/crates/ra_assists/src/handlers/move_bounds.rs
+++ b/crates/ra_assists/src/handlers/move_bounds.rs
@@ -2,6 +2,7 @@ use ra_syntax::{
2 ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner}, 2 ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner},
3 match_ast, 3 match_ast,
4 SyntaxKind::*, 4 SyntaxKind::*,
5 T,
5}; 6};
6 7
7use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
@@ -42,7 +43,7 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> {
42 ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(), 43 ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(),
43 ast::StructDef(it) => { 44 ast::StructDef(it) => {
44 it.syntax().children_with_tokens() 45 it.syntax().children_with_tokens()
45 .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == SEMI)? 46 .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == T![;])?
46 }, 47 },
47 _ => return None 48 _ => return None
48 } 49 }
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 45631f8fd..226fb4534 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -255,7 +255,7 @@ impl SourceAnalyzer {
255 _ => return None, 255 _ => return None,
256 }; 256 };
257 257
258 let (variant, missing_fields) = 258 let (variant, missing_fields, _exhaustive) =
259 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; 259 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
260 let res = self.missing_fields(db, krate, substs, variant, missing_fields); 260 let res = self.missing_fields(db, krate, substs, variant, missing_fields);
261 Some(res) 261 Some(res)
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 7fc4cd76e..be4b0accb 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -4,6 +4,7 @@ use std::sync::Arc;
4 4
5use either::Either; 5use either::Either;
6use hir_expand::{ 6use hir_expand::{
7 hygiene::Hygiene,
7 name::{AsName, Name}, 8 name::{AsName, Name},
8 InFile, 9 InFile,
9}; 10};
@@ -12,9 +13,9 @@ use ra_prof::profile;
12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 13use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
13 14
14use crate::{ 15use crate::{
15 db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, 16 attr::Attrs, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
16 visibility::RawVisibility, EnumId, LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, 17 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
17 UnionId, VariantId, 18 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
18}; 19};
19 20
20/// Note that we use `StructData` for unions as well! 21/// Note that we use `StructData` for unions as well!
@@ -56,7 +57,8 @@ impl StructData {
56 let src = id.lookup(db).source(db); 57 let src = id.lookup(db).source(db);
57 58
58 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 59 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
59 let variant_data = VariantData::new(db, src.map(|s| s.kind())); 60 let variant_data =
61 VariantData::new(db, src.map(|s| s.kind()), id.lookup(db).container.module(db));
60 let variant_data = Arc::new(variant_data); 62 let variant_data = Arc::new(variant_data);
61 Arc::new(StructData { name, variant_data }) 63 Arc::new(StructData { name, variant_data })
62 } 64 }
@@ -70,6 +72,7 @@ impl StructData {
70 .map(ast::StructKind::Record) 72 .map(ast::StructKind::Record)
71 .unwrap_or(ast::StructKind::Unit) 73 .unwrap_or(ast::StructKind::Unit)
72 }), 74 }),
75 id.lookup(db).container.module(db),
73 ); 76 );
74 let variant_data = Arc::new(variant_data); 77 let variant_data = Arc::new(variant_data);
75 Arc::new(StructData { name, variant_data }) 78 Arc::new(StructData { name, variant_data })
@@ -82,7 +85,7 @@ impl EnumData {
82 let src = e.lookup(db).source(db); 85 let src = e.lookup(db).source(db);
83 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 86 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
84 let mut trace = Trace::new_for_arena(); 87 let mut trace = Trace::new_for_arena();
85 lower_enum(db, &mut trace, &src); 88 lower_enum(db, &mut trace, &src, e.lookup(db).container.module(db));
86 Arc::new(EnumData { name, variants: trace.into_arena() }) 89 Arc::new(EnumData { name, variants: trace.into_arena() })
87 } 90 }
88 91
@@ -98,7 +101,7 @@ impl HasChildSource for EnumId {
98 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 101 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> {
99 let src = self.lookup(db).source(db); 102 let src = self.lookup(db).source(db);
100 let mut trace = Trace::new_for_map(); 103 let mut trace = Trace::new_for_map();
101 lower_enum(db, &mut trace, &src); 104 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db));
102 src.with_value(trace.into_map()) 105 src.with_value(trace.into_map())
103 } 106 }
104} 107}
@@ -107,22 +110,23 @@ fn lower_enum(
107 db: &dyn DefDatabase, 110 db: &dyn DefDatabase,
108 trace: &mut Trace<EnumVariantData, ast::EnumVariant>, 111 trace: &mut Trace<EnumVariantData, ast::EnumVariant>,
109 ast: &InFile<ast::EnumDef>, 112 ast: &InFile<ast::EnumDef>,
113 module_id: ModuleId,
110) { 114) {
111 for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { 115 for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) {
112 trace.alloc( 116 trace.alloc(
113 || var.clone(), 117 || var.clone(),
114 || EnumVariantData { 118 || EnumVariantData {
115 name: var.name().map_or_else(Name::missing, |it| it.as_name()), 119 name: var.name().map_or_else(Name::missing, |it| it.as_name()),
116 variant_data: Arc::new(VariantData::new(db, ast.with_value(var.kind()))), 120 variant_data: Arc::new(VariantData::new(db, ast.with_value(var.kind()), module_id)),
117 }, 121 },
118 ); 122 );
119 } 123 }
120} 124}
121 125
122impl VariantData { 126impl VariantData {
123 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>) -> Self { 127 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self {
124 let mut trace = Trace::new_for_arena(); 128 let mut trace = Trace::new_for_arena();
125 match lower_struct(db, &mut trace, &flavor) { 129 match lower_struct(db, &mut trace, &flavor, module_id) {
126 StructKind::Tuple => VariantData::Tuple(trace.into_arena()), 130 StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
127 StructKind::Record => VariantData::Record(trace.into_arena()), 131 StructKind::Record => VariantData::Record(trace.into_arena()),
128 StructKind::Unit => VariantData::Unit, 132 StructKind::Unit => VariantData::Unit,
@@ -155,22 +159,27 @@ impl HasChildSource for VariantId {
155 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>; 159 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>;
156 160
157 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 161 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> {
158 let src = match self { 162 let (src, module_id) = match self {
159 VariantId::EnumVariantId(it) => { 163 VariantId::EnumVariantId(it) => {
160 // I don't really like the fact that we call into parent source 164 // I don't really like the fact that we call into parent source
161 // here, this might add to more queries then necessary. 165 // here, this might add to more queries then necessary.
162 let src = it.parent.child_source(db); 166 let src = it.parent.child_source(db);
163 src.map(|map| map[it.local_id].kind()) 167 (src.map(|map| map[it.local_id].kind()), it.parent.lookup(db).container.module(db))
164 } 168 }
165 VariantId::StructId(it) => it.lookup(db).source(db).map(|it| it.kind()), 169 VariantId::StructId(it) => {
166 VariantId::UnionId(it) => it.lookup(db).source(db).map(|it| { 170 (it.lookup(db).source(db).map(|it| it.kind()), it.lookup(db).container.module(db))
167 it.record_field_def_list() 171 }
168 .map(ast::StructKind::Record) 172 VariantId::UnionId(it) => (
169 .unwrap_or(ast::StructKind::Unit) 173 it.lookup(db).source(db).map(|it| {
170 }), 174 it.record_field_def_list()
175 .map(ast::StructKind::Record)
176 .unwrap_or(ast::StructKind::Unit)
177 }),
178 it.lookup(db).container.module(db),
179 ),
171 }; 180 };
172 let mut trace = Trace::new_for_map(); 181 let mut trace = Trace::new_for_map();
173 lower_struct(db, &mut trace, &src); 182 lower_struct(db, &mut trace, &src, module_id);
174 src.with_value(trace.into_map()) 183 src.with_value(trace.into_map())
175 } 184 }
176} 185}
@@ -186,10 +195,17 @@ fn lower_struct(
186 db: &dyn DefDatabase, 195 db: &dyn DefDatabase,
187 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 196 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
188 ast: &InFile<ast::StructKind>, 197 ast: &InFile<ast::StructKind>,
198 module_id: ModuleId,
189) -> StructKind { 199) -> StructKind {
200 let crate_graph = db.crate_graph();
190 match &ast.value { 201 match &ast.value {
191 ast::StructKind::Tuple(fl) => { 202 ast::StructKind::Tuple(fl) => {
192 for (i, fd) in fl.fields().enumerate() { 203 for (i, fd) in fl.fields().enumerate() {
204 let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id));
205 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
206 continue;
207 }
208
193 trace.alloc( 209 trace.alloc(
194 || Either::Left(fd.clone()), 210 || Either::Left(fd.clone()),
195 || StructFieldData { 211 || StructFieldData {
@@ -203,6 +219,11 @@ fn lower_struct(
203 } 219 }
204 ast::StructKind::Record(fl) => { 220 ast::StructKind::Record(fl) => {
205 for fd in fl.fields() { 221 for fd in fl.fields() {
222 let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id));
223 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
224 continue;
225 }
226
206 trace.alloc( 227 trace.alloc(
207 || Either::Right(fd.clone()), 228 || Either::Right(fd.clone()),
208 || StructFieldData { 229 || StructFieldData {
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 71a18f5e1..7b0c506b1 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -5,6 +5,7 @@ use std::{ops, sync::Arc};
5use either::Either; 5use either::Either;
6use hir_expand::{hygiene::Hygiene, AstId, InFile}; 6use hir_expand::{hygiene::Hygiene, AstId, InFile};
7use mbe::ast_to_token_tree; 7use mbe::ast_to_token_tree;
8use ra_cfg::CfgOptions;
8use ra_syntax::{ 9use ra_syntax::{
9 ast::{self, AstNode, AttrsOwner}, 10 ast::{self, AstNode, AttrsOwner},
10 SmolStr, 11 SmolStr,
@@ -90,6 +91,10 @@ impl Attrs {
90 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { 91 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
91 AttrQuery { attrs: self, key } 92 AttrQuery { attrs: self, key }
92 } 93 }
94
95 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
96 self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false))
97 }
93} 98}
94 99
95#[derive(Debug, Clone, PartialEq, Eq)] 100#[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 5f9d53ecb..e09996c6f 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -236,7 +236,7 @@ impl Index<PatId> for Body {
236 236
237impl BodySourceMap { 237impl BodySourceMap {
238 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { 238 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
239 self.expr_map_back[expr] 239 self.expr_map_back[expr].clone()
240 } 240 }
241 241
242 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { 242 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
@@ -255,7 +255,7 @@ impl BodySourceMap {
255 } 255 }
256 256
257 pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { 257 pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
258 self.pat_map_back[pat] 258 self.pat_map_back[pat].clone()
259 } 259 }
260 260
261 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> { 261 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
@@ -264,6 +264,6 @@ impl BodySourceMap {
264 } 264 }
265 265
266 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> { 266 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
267 self.field_map[&(expr, field)] 267 self.field_map[&(expr, field)].clone()
268 } 268 }
269} 269}
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index c4a5ec59c..9d6ee095e 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -4,6 +4,7 @@
4use either::Either; 4use either::Either;
5 5
6use hir_expand::{ 6use hir_expand::{
7 hygiene::Hygiene,
7 name::{name, AsName, Name}, 8 name::{name, AsName, Name},
8 MacroDefId, MacroDefKind, 9 MacroDefId, MacroDefKind,
9}; 10};
@@ -20,6 +21,7 @@ use test_utils::tested_by;
20use super::{ExprSource, PatSource}; 21use super::{ExprSource, PatSource};
21use crate::{ 22use crate::{
22 adt::StructKind, 23 adt::StructKind,
24 attr::Attrs,
23 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, 25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
24 builtin_type::{BuiltinFloat, BuiltinInt}, 26 builtin_type::{BuiltinFloat, BuiltinInt},
25 db::DefDatabase, 27 db::DefDatabase,
@@ -31,8 +33,8 @@ use crate::{
31 path::GenericArgs, 33 path::GenericArgs,
32 path::Path, 34 path::Path,
33 type_ref::{Mutability, TypeRef}, 35 type_ref::{Mutability, TypeRef},
34 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, 36 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, HasModule, Intern,
35 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 37 ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
36}; 38};
37 39
38pub(super) fn lower( 40pub(super) fn lower(
@@ -104,7 +106,7 @@ impl ExprCollector<'_> {
104 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 106 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
105 let ptr = Either::Left(ptr); 107 let ptr = Either::Left(ptr);
106 let src = self.expander.to_source(ptr); 108 let src = self.expander.to_source(ptr);
107 let id = self.make_expr(expr, Ok(src)); 109 let id = self.make_expr(expr, Ok(src.clone()));
108 self.source_map.expr_map.insert(src, id); 110 self.source_map.expr_map.insert(src, id);
109 id 111 id
110 } 112 }
@@ -116,7 +118,7 @@ impl ExprCollector<'_> {
116 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId { 118 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
117 let ptr = Either::Right(ptr); 119 let ptr = Either::Right(ptr);
118 let src = self.expander.to_source(ptr); 120 let src = self.expander.to_source(ptr);
119 let id = self.make_expr(expr, Ok(src)); 121 let id = self.make_expr(expr, Ok(src.clone()));
120 self.source_map.expr_map.insert(src, id); 122 self.source_map.expr_map.insert(src, id);
121 id 123 id
122 } 124 }
@@ -134,7 +136,7 @@ impl ExprCollector<'_> {
134 136
135 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { 137 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
136 let src = self.expander.to_source(ptr); 138 let src = self.expander.to_source(ptr);
137 let id = self.make_pat(pat, Ok(src)); 139 let id = self.make_pat(pat, Ok(src.clone()));
138 self.source_map.pat_map.insert(src, id); 140 self.source_map.pat_map.insert(src, id);
139 id 141 id
140 } 142 }
@@ -298,28 +300,41 @@ impl ExprCollector<'_> {
298 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 300 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
299 } 301 }
300 ast::Expr::RecordLit(e) => { 302 ast::Expr::RecordLit(e) => {
303 let crate_graph = self.db.crate_graph();
301 let path = e.path().and_then(|path| self.expander.parse_path(path)); 304 let path = e.path().and_then(|path| self.expander.parse_path(path));
302 let mut field_ptrs = Vec::new(); 305 let mut field_ptrs = Vec::new();
303 let record_lit = if let Some(nfl) = e.record_field_list() { 306 let record_lit = if let Some(nfl) = e.record_field_list() {
304 let fields = nfl 307 let fields = nfl
305 .fields() 308 .fields()
306 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 309 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
307 .map(|field| RecordLitField { 310 .filter_map(|field| {
308 name: field 311 let module_id = ContainerId::DefWithBodyId(self.def).module(self.db);
309 .name_ref() 312 let attrs = Attrs::new(
310 .map(|nr| nr.as_name()) 313 &field,
311 .unwrap_or_else(Name::missing), 314 &Hygiene::new(self.db.upcast(), self.expander.current_file_id),
312 expr: if let Some(e) = field.expr() { 315 );
313 self.collect_expr(e) 316
314 } else if let Some(nr) = field.name_ref() { 317 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
315 // field shorthand 318 return None;
316 self.alloc_expr_field_shorthand( 319 }
317 Expr::Path(Path::from_name_ref(&nr)), 320
318 AstPtr::new(&field), 321 Some(RecordLitField {
319 ) 322 name: field
320 } else { 323 .name_ref()
321 self.missing_expr() 324 .map(|nr| nr.as_name())
322 }, 325 .unwrap_or_else(Name::missing),
326 expr: if let Some(e) = field.expr() {
327 self.collect_expr(e)
328 } else if let Some(nr) = field.name_ref() {
329 // field shorthand
330 self.alloc_expr_field_shorthand(
331 Expr::Path(Path::from_name_ref(&nr)),
332 AstPtr::new(&field),
333 )
334 } else {
335 self.missing_expr()
336 },
337 })
323 }) 338 })
324 .collect(); 339 .collect();
325 let spread = nfl.spread().map(|s| self.collect_expr(s)); 340 let spread = nfl.spread().map(|s| self.collect_expr(s));
@@ -357,7 +372,7 @@ impl ExprCollector<'_> {
357 } 372 }
358 ast::Expr::RefExpr(e) => { 373 ast::Expr::RefExpr(e) => {
359 let expr = self.collect_expr_opt(e.expr()); 374 let expr = self.collect_expr_opt(e.expr());
360 let mutability = Mutability::from_mutable(e.is_mut()); 375 let mutability = Mutability::from_mutable(e.mut_token().is_some());
361 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) 376 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr)
362 } 377 }
363 ast::Expr::PrefixExpr(e) => { 378 ast::Expr::PrefixExpr(e) => {
@@ -572,10 +587,8 @@ impl ExprCollector<'_> {
572 let pattern = match &pat { 587 let pattern = match &pat {
573 ast::Pat::BindPat(bp) => { 588 ast::Pat::BindPat(bp) => {
574 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 589 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
575 let annotation = BindingAnnotation::new( 590 let annotation =
576 bp.mut_kw_token().is_some(), 591 BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
577 bp.ref_kw_token().is_some(),
578 );
579 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat)); 592 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
580 if annotation == BindingAnnotation::Unannotated && subpat.is_none() { 593 if annotation == BindingAnnotation::Unannotated && subpat.is_none() {
581 // This could also be a single-segment path pattern. To 594 // This could also be a single-segment path pattern. To
@@ -616,7 +629,7 @@ impl ExprCollector<'_> {
616 } 629 }
617 ast::Pat::RefPat(p) => { 630 ast::Pat::RefPat(p) => {
618 let pat = self.collect_pat_opt(p.pat()); 631 let pat = self.collect_pat_opt(p.pat());
619 let mutability = Mutability::from_mutable(p.mut_kw_token().is_some()); 632 let mutability = Mutability::from_mutable(p.mut_token().is_some());
620 Pat::Ref { pat, mutability } 633 Pat::Ref { pat, mutability }
621 } 634 }
622 ast::Pat::PathPat(p) => { 635 ast::Pat::PathPat(p) => {
@@ -655,7 +668,9 @@ impl ExprCollector<'_> {
655 }); 668 });
656 fields.extend(iter); 669 fields.extend(iter);
657 670
658 Pat::Record { path, args: fields } 671 let ellipsis = record_field_pat_list.dotdot_token().is_some();
672
673 Pat::Record { path, args: fields, ellipsis }
659 } 674 }
660 ast::Pat::SlicePat(p) => { 675 ast::Pat::SlicePat(p) => {
661 let SlicePatComponents { prefix, slice, suffix } = p.components(); 676 let SlicePatComponents { prefix, slice, suffix } = p.components();
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 689bb6c5c..b8fbf0ed4 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -7,7 +7,6 @@ use hir_expand::{
7 name::{name, AsName, Name}, 7 name::{name, AsName, Name},
8 AstId, InFile, 8 AstId, InFile,
9}; 9};
10use ra_cfg::CfgOptions;
11use ra_prof::profile; 10use ra_prof::profile;
12use ra_syntax::ast::{ 11use ra_syntax::ast::{
13 self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, 12 self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner,
@@ -75,7 +74,7 @@ impl FunctionData {
75 TypeRef::unit() 74 TypeRef::unit()
76 }; 75 };
77 76
78 let ret_type = if src.value.async_kw_token().is_some() { 77 let ret_type = if src.value.async_token().is_some() {
79 let future_impl = desugar_future_path(ret_type); 78 let future_impl = desugar_future_path(ret_type);
80 let ty_bound = TypeBound::Path(future_impl); 79 let ty_bound = TypeBound::Path(future_impl);
81 TypeRef::ImplTrait(vec![ty_bound]) 80 TypeRef::ImplTrait(vec![ty_bound])
@@ -136,7 +135,7 @@ impl TraitData {
136 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 135 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
137 let src = tr.lookup(db).source(db); 136 let src = tr.lookup(db).source(db);
138 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 137 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
139 let auto = src.value.auto_kw_token().is_some(); 138 let auto = src.value.auto_token().is_some();
140 let ast_id_map = db.ast_id_map(src.file_id); 139 let ast_id_map = db.ast_id_map(src.file_id);
141 140
142 let container = AssocContainerId::TraitId(tr); 141 let container = AssocContainerId::TraitId(tr);
@@ -318,10 +317,6 @@ fn collect_impl_items_in_macro(
318 } 317 }
319} 318}
320 319
321fn is_cfg_enabled(cfg_options: &CfgOptions, attrs: &Attrs) -> bool {
322 attrs.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false))
323}
324
325fn collect_impl_items( 320fn collect_impl_items(
326 db: &dyn DefDatabase, 321 db: &dyn DefDatabase,
327 impl_items: impl Iterator<Item = ImplItem>, 322 impl_items: impl Iterator<Item = ImplItem>,
@@ -341,10 +336,11 @@ fn collect_impl_items(
341 } 336 }
342 .intern(db); 337 .intern(db);
343 338
344 if !is_cfg_enabled( 339 if !db
345 &crate_graph[module_id.krate].cfg_options, 340 .function_data(def)
346 &db.function_data(def).attrs, 341 .attrs
347 ) { 342 .is_cfg_enabled(&crate_graph[module_id.krate].cfg_options)
343 {
348 None 344 None
349 } else { 345 } else {
350 Some(def.into()) 346 Some(def.into())
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index 095498429..cfa0f2f76 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -20,7 +20,7 @@ impl Diagnostic for UnresolvedModule {
20 "unresolved module".to_string() 20 "unresolved module".to_string()
21 } 21 }
22 fn source(&self) -> InFile<SyntaxNodePtr> { 22 fn source(&self) -> InFile<SyntaxNodePtr> {
23 InFile { file_id: self.file, value: self.decl.into() } 23 InFile { file_id: self.file, value: self.decl.clone().into() }
24 } 24 }
25 fn as_any(&self) -> &(dyn Any + Send + 'static) { 25 fn as_any(&self) -> &(dyn Any + Send + 'static) {
26 self 26 self
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index 197bbe9bd..e11bdf3ec 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -376,35 +376,14 @@ pub enum Pat {
376 Wild, 376 Wild,
377 Tuple(Vec<PatId>), 377 Tuple(Vec<PatId>),
378 Or(Vec<PatId>), 378 Or(Vec<PatId>),
379 Record { 379 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool },
380 path: Option<Path>, 380 Range { start: ExprId, end: ExprId },
381 args: Vec<RecordFieldPat>, 381 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
382 // FIXME: 'ellipsis' option
383 },
384 Range {
385 start: ExprId,
386 end: ExprId,
387 },
388 Slice {
389 prefix: Vec<PatId>,
390 slice: Option<PatId>,
391 suffix: Vec<PatId>,
392 },
393 Path(Path), 382 Path(Path),
394 Lit(ExprId), 383 Lit(ExprId),
395 Bind { 384 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
396 mode: BindingAnnotation, 385 TupleStruct { path: Option<Path>, args: Vec<PatId> },
397 name: Name, 386 Ref { pat: PatId, mutability: Mutability },
398 subpat: Option<PatId>,
399 },
400 TupleStruct {
401 path: Option<Path>,
402 args: Vec<PatId>,
403 },
404 Ref {
405 pat: PatId,
406 mutability: Mutability,
407 },
408} 387}
409 388
410impl Pat { 389impl Pat {
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index 01b367278..d96ac8c0a 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -4,6 +4,7 @@
4//! features, such as Fn family of traits. 4//! features, such as Fn family of traits.
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use ra_prof::profile;
7use ra_syntax::SmolStr; 8use ra_syntax::SmolStr;
8use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
9 10
@@ -78,6 +79,8 @@ impl LangItems {
78 79
79 /// Salsa query. This will look for lang items in a specific crate. 80 /// Salsa query. This will look for lang items in a specific crate.
80 pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> { 81 pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> {
82 let _p = profile("crate_lang_items_query");
83
81 let mut lang_items = LangItems::default(); 84 let mut lang_items = LangItems::default();
82 85
83 let crate_def_map = db.crate_def_map(krate); 86 let crate_def_map = db.crate_def_map(krate);
@@ -95,6 +98,7 @@ impl LangItems {
95 db: &dyn DefDatabase, 98 db: &dyn DefDatabase,
96 module: ModuleId, 99 module: ModuleId,
97 ) -> Option<Arc<LangItems>> { 100 ) -> Option<Arc<LangItems>> {
101 let _p = profile("module_lang_items_query");
98 let mut lang_items = LangItems::default(); 102 let mut lang_items = LangItems::default();
99 lang_items.collect_lang_items(db, module); 103 lang_items.collect_lang_items(db, module);
100 if lang_items.items.is_empty() { 104 if lang_items.items.is_empty() {
@@ -111,6 +115,7 @@ impl LangItems {
111 start_crate: CrateId, 115 start_crate: CrateId,
112 item: SmolStr, 116 item: SmolStr,
113 ) -> Option<LangItemTarget> { 117 ) -> Option<LangItemTarget> {
118 let _p = profile("lang_item_query");
114 let lang_items = db.crate_lang_items(start_crate); 119 let lang_items = db.crate_lang_items(start_crate);
115 let start_crate_target = lang_items.items.get(&item); 120 let start_crate_target = lang_items.items.get(&item);
116 if let Some(target) = start_crate_target { 121 if let Some(target) = start_crate_target {
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index e72ba52cf..afd538e4a 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -287,7 +287,7 @@ impl RawItemsCollector {
287 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); 287 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene);
288 288
289 let ast_id = self.source_ast_id_map.ast_id(&module); 289 let ast_id = self.source_ast_id_map.ast_id(&module);
290 if module.semi_token().is_some() { 290 if module.semicolon_token().is_some() {
291 let item = 291 let item =
292 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); 292 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id });
293 self.push_item(current_module, attrs, RawItemKind::Module(item)); 293 self.push_item(current_module, attrs, RawItemKind::Module(item));
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index 7a8338937..ea29c4176 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -77,7 +77,7 @@ impl TypeRef {
77 } 77 }
78 ast::TypeRef::PointerType(inner) => { 78 ast::TypeRef::PointerType(inner) => {
79 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 79 let inner_ty = TypeRef::from_ast_opt(inner.type_ref());
80 let mutability = Mutability::from_mutable(inner.mut_kw_token().is_some()); 80 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
81 TypeRef::RawPtr(Box::new(inner_ty), mutability) 81 TypeRef::RawPtr(Box::new(inner_ty), mutability)
82 } 82 }
83 ast::TypeRef::ArrayType(inner) => { 83 ast::TypeRef::ArrayType(inner) => {
@@ -88,7 +88,7 @@ impl TypeRef {
88 } 88 }
89 ast::TypeRef::ReferenceType(inner) => { 89 ast::TypeRef::ReferenceType(inner) => {
90 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 90 let inner_ty = TypeRef::from_ast_opt(inner.type_ref());
91 let mutability = Mutability::from_mutable(inner.mut_kw_token().is_some()); 91 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
92 TypeRef::Reference(Box::new(inner_ty), mutability) 92 TypeRef::Reference(Box::new(inner_ty), mutability)
93 } 93 }
94 ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder, 94 ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder,
diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs
index 5643ecdce..a3ca302c2 100644
--- a/crates/ra_hir_expand/src/ast_id_map.rs
+++ b/crates/ra_hir_expand/src/ast_id_map.rs
@@ -90,7 +90,7 @@ impl AstIdMap {
90 } 90 }
91 91
92 pub(crate) fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> { 92 pub(crate) fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> {
93 self.arena[id.raw].cast::<N>().unwrap() 93 self.arena[id.raw].clone().cast::<N>().unwrap()
94 } 94 }
95 95
96 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId { 96 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 9a4a7aa6f..59efc1c31 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -24,6 +24,8 @@ ra_prof = { path = "../ra_prof" }
24ra_syntax = { path = "../ra_syntax" } 24ra_syntax = { path = "../ra_syntax" }
25test_utils = { path = "../test_utils" } 25test_utils = { path = "../test_utils" }
26 26
27scoped-tls = "1"
28
27chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } 29chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
28chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } 30chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
29chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } 31chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 8cbce1168..927896d6f 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -21,7 +21,7 @@ impl Diagnostic for NoSuchField {
21 } 21 }
22 22
23 fn source(&self) -> InFile<SyntaxNodePtr> { 23 fn source(&self) -> InFile<SyntaxNodePtr> {
24 InFile { file_id: self.file, value: self.field.into() } 24 InFile { file_id: self.file, value: self.field.clone().into() }
25 } 25 }
26 26
27 fn as_any(&self) -> &(dyn Any + Send + 'static) { 27 fn as_any(&self) -> &(dyn Any + Send + 'static) {
@@ -45,7 +45,7 @@ impl Diagnostic for MissingFields {
45 buf 45 buf
46 } 46 }
47 fn source(&self) -> InFile<SyntaxNodePtr> { 47 fn source(&self) -> InFile<SyntaxNodePtr> {
48 InFile { file_id: self.file, value: self.field_list.into() } 48 InFile { file_id: self.file, value: self.field_list.clone().into() }
49 } 49 }
50 fn as_any(&self) -> &(dyn Any + Send + 'static) { 50 fn as_any(&self) -> &(dyn Any + Send + 'static) {
51 self 51 self
@@ -63,6 +63,29 @@ impl AstDiagnostic for MissingFields {
63} 63}
64 64
65#[derive(Debug)] 65#[derive(Debug)]
66pub struct MissingPatFields {
67 pub file: HirFileId,
68 pub field_list: AstPtr<ast::RecordFieldPatList>,
69 pub missed_fields: Vec<Name>,
70}
71
72impl Diagnostic for MissingPatFields {
73 fn message(&self) -> String {
74 let mut buf = String::from("Missing structure fields:\n");
75 for field in &self.missed_fields {
76 format_to!(buf, "- {}", field);
77 }
78 buf
79 }
80 fn source(&self) -> InFile<SyntaxNodePtr> {
81 InFile { file_id: self.file, value: self.field_list.clone().into() }
82 }
83 fn as_any(&self) -> &(dyn Any + Send + 'static) {
84 self
85 }
86}
87
88#[derive(Debug)]
66pub struct MissingMatchArms { 89pub struct MissingMatchArms {
67 pub file: HirFileId, 90 pub file: HirFileId,
68 pub match_expr: AstPtr<ast::Expr>, 91 pub match_expr: AstPtr<ast::Expr>,
@@ -74,7 +97,7 @@ impl Diagnostic for MissingMatchArms {
74 String::from("Missing match arm") 97 String::from("Missing match arm")
75 } 98 }
76 fn source(&self) -> InFile<SyntaxNodePtr> { 99 fn source(&self) -> InFile<SyntaxNodePtr> {
77 InFile { file_id: self.file, value: self.match_expr.into() } 100 InFile { file_id: self.file, value: self.match_expr.clone().into() }
78 } 101 }
79 fn as_any(&self) -> &(dyn Any + Send + 'static) { 102 fn as_any(&self) -> &(dyn Any + Send + 'static) {
80 self 103 self
@@ -92,7 +115,7 @@ impl Diagnostic for MissingOkInTailExpr {
92 "wrap return expression in Ok".to_string() 115 "wrap return expression in Ok".to_string()
93 } 116 }
94 fn source(&self) -> InFile<SyntaxNodePtr> { 117 fn source(&self) -> InFile<SyntaxNodePtr> {
95 InFile { file_id: self.file, value: self.expr.into() } 118 InFile { file_id: self.file, value: self.expr.clone().into() }
96 } 119 }
97 fn as_any(&self) -> &(dyn Any + Send + 'static) { 120 fn as_any(&self) -> &(dyn Any + Send + 'static) {
98 self 121 self
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 0e9313aa1..d03bbd5a7 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -247,19 +247,21 @@ impl HirDisplay for ApplicationTy {
247 } 247 }
248 } 248 }
249 TypeCtor::Closure { .. } => { 249 TypeCtor::Closure { .. } => {
250 let sig = self.parameters[0] 250 let sig = self.parameters[0].callable_sig(f.db);
251 .callable_sig(f.db) 251 if let Some(sig) = sig {
252 .expect("first closure parameter should contain signature"); 252 if sig.params().is_empty() {
253 if sig.params().is_empty() { 253 write!(f, "||")?;
254 write!(f, "||")?; 254 } else if f.omit_verbose_types() {
255 } else if f.omit_verbose_types() { 255 write!(f, "|{}|", TYPE_HINT_TRUNCATION)?;
256 write!(f, "|{}|", TYPE_HINT_TRUNCATION)?; 256 } else {
257 write!(f, "|")?;
258 f.write_joined(sig.params(), ", ")?;
259 write!(f, "|")?;
260 };
261 write!(f, " -> {}", sig.ret().display(f.db))?;
257 } else { 262 } else {
258 write!(f, "|")?; 263 write!(f, "{{closure}}")?;
259 f.write_joined(sig.params(), ", ")?; 264 }
260 write!(f, "|")?;
261 };
262 write!(f, " -> {}", sig.ret().display(f.db))?;
263 } 265 }
264 } 266 }
265 Ok(()) 267 Ok(())
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index e45e9ea14..827b687de 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -9,7 +9,7 @@ use rustc_hash::FxHashSet;
9 9
10use crate::{ 10use crate::{
11 db::HirDatabase, 11 db::HirDatabase,
12 diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr}, 12 diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields},
13 utils::variant_data, 13 utils::variant_data,
14 ApplicationTy, InferenceResult, Ty, TypeCtor, 14 ApplicationTy, InferenceResult, Ty, TypeCtor,
15 _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, 15 _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness},
@@ -49,39 +49,97 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
49 if let Some((variant_def, missed_fields, true)) = 49 if let Some((variant_def, missed_fields, true)) =
50 record_literal_missing_fields(db, &self.infer, id, expr) 50 record_literal_missing_fields(db, &self.infer, id, expr)
51 { 51 {
52 // XXX: only look at source_map if we do have missing fields 52 self.create_record_literal_missing_fields_diagnostic(
53 let (_, source_map) = db.body_with_source_map(self.func.into()); 53 id,
54 54 db,
55 if let Ok(source_ptr) = source_map.expr_syntax(id) { 55 variant_def,
56 if let Some(expr) = source_ptr.value.left() { 56 missed_fields,
57 let root = source_ptr.file_syntax(db.upcast()); 57 );
58 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) {
59 if let Some(field_list) = record_lit.record_field_list() {
60 let variant_data = variant_data(db.upcast(), variant_def);
61 let missed_fields = missed_fields
62 .into_iter()
63 .map(|idx| variant_data.fields()[idx].name.clone())
64 .collect();
65 self.sink.push(MissingFields {
66 file: source_ptr.file_id,
67 field_list: AstPtr::new(&field_list),
68 missed_fields,
69 })
70 }
71 }
72 }
73 }
74 } 58 }
75 if let Expr::Match { expr, arms } = expr { 59 if let Expr::Match { expr, arms } = expr {
76 self.validate_match(id, *expr, arms, db, self.infer.clone()); 60 self.validate_match(id, *expr, arms, db, self.infer.clone());
77 } 61 }
78 } 62 }
63 for (id, pat) in body.pats.iter() {
64 if let Some((variant_def, missed_fields, true)) =
65 record_pattern_missing_fields(db, &self.infer, id, pat)
66 {
67 self.create_record_pattern_missing_fields_diagnostic(
68 id,
69 db,
70 variant_def,
71 missed_fields,
72 );
73 }
74 }
79 let body_expr = &body[body.body_expr]; 75 let body_expr = &body[body.body_expr];
80 if let Expr::Block { tail: Some(t), .. } = body_expr { 76 if let Expr::Block { tail: Some(t), .. } = body_expr {
81 self.validate_results_in_tail_expr(body.body_expr, *t, db); 77 self.validate_results_in_tail_expr(body.body_expr, *t, db);
82 } 78 }
83 } 79 }
84 80
81 fn create_record_literal_missing_fields_diagnostic(
82 &mut self,
83 id: ExprId,
84 db: &dyn HirDatabase,
85 variant_def: VariantId,
86 missed_fields: Vec<LocalStructFieldId>,
87 ) {
88 // XXX: only look at source_map if we do have missing fields
89 let (_, source_map) = db.body_with_source_map(self.func.into());
90
91 if let Ok(source_ptr) = source_map.expr_syntax(id) {
92 if let Some(expr) = source_ptr.value.as_ref().left() {
93 let root = source_ptr.file_syntax(db.upcast());
94 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) {
95 if let Some(field_list) = record_lit.record_field_list() {
96 let variant_data = variant_data(db.upcast(), variant_def);
97 let missed_fields = missed_fields
98 .into_iter()
99 .map(|idx| variant_data.fields()[idx].name.clone())
100 .collect();
101 self.sink.push(MissingFields {
102 file: source_ptr.file_id,
103 field_list: AstPtr::new(&field_list),
104 missed_fields,
105 })
106 }
107 }
108 }
109 }
110 }
111
112 fn create_record_pattern_missing_fields_diagnostic(
113 &mut self,
114 id: PatId,
115 db: &dyn HirDatabase,
116 variant_def: VariantId,
117 missed_fields: Vec<LocalStructFieldId>,
118 ) {
119 // XXX: only look at source_map if we do have missing fields
120 let (_, source_map) = db.body_with_source_map(self.func.into());
121
122 if let Ok(source_ptr) = source_map.pat_syntax(id) {
123 if let Some(expr) = source_ptr.value.as_ref().left() {
124 let root = source_ptr.file_syntax(db.upcast());
125 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
126 if let Some(field_list) = record_pat.record_field_pat_list() {
127 let variant_data = variant_data(db.upcast(), variant_def);
128 let missed_fields = missed_fields
129 .into_iter()
130 .map(|idx| variant_data.fields()[idx].name.clone())
131 .collect();
132 self.sink.push(MissingPatFields {
133 file: source_ptr.file_id,
134 field_list: AstPtr::new(&field_list),
135 missed_fields,
136 })
137 }
138 }
139 }
140 }
141 }
142
85 fn validate_match( 143 fn validate_match(
86 &mut self, 144 &mut self,
87 id: ExprId, 145 id: ExprId,
@@ -147,7 +205,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
147 } 205 }
148 206
149 if let Ok(source_ptr) = source_map.expr_syntax(id) { 207 if let Ok(source_ptr) = source_map.expr_syntax(id) {
150 if let Some(expr) = source_ptr.value.left() { 208 if let Some(expr) = source_ptr.value.as_ref().left() {
151 let root = source_ptr.file_syntax(db.upcast()); 209 let root = source_ptr.file_syntax(db.upcast());
152 if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) { 210 if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) {
153 if let (Some(match_expr), Some(arms)) = 211 if let (Some(match_expr), Some(arms)) =
@@ -232,9 +290,9 @@ pub fn record_pattern_missing_fields(
232 infer: &InferenceResult, 290 infer: &InferenceResult,
233 id: PatId, 291 id: PatId,
234 pat: &Pat, 292 pat: &Pat,
235) -> Option<(VariantId, Vec<LocalStructFieldId>)> { 293) -> Option<(VariantId, Vec<LocalStructFieldId>, /*exhaustive*/ bool)> {
236 let fields = match pat { 294 let (fields, exhaustive) = match pat {
237 Pat::Record { path: _, args } => args, 295 Pat::Record { path: _, args, ellipsis } => (args, !ellipsis),
238 _ => return None, 296 _ => return None,
239 }; 297 };
240 298
@@ -254,5 +312,5 @@ pub fn record_pattern_missing_fields(
254 if missed_fields.is_empty() { 312 if missed_fields.is_empty() {
255 return None; 313 return None;
256 } 314 }
257 Some((variant_def, missed_fields)) 315 Some((variant_def, missed_fields, exhaustive))
258} 316}
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 69bbb4307..078476f76 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> {
158 Pat::TupleStruct { path: p, args: subpats } => { 158 Pat::TupleStruct { path: p, args: subpats } => {
159 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm, pat) 159 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm, pat)
160 } 160 }
161 Pat::Record { path: p, args: fields } => { 161 Pat::Record { path: p, args: fields, ellipsis: _ } => {
162 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 162 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
163 } 163 }
164 Pat::Path(path) => { 164 Pat::Path(path) => {
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index f97e0bfeb..54e31602f 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -23,7 +23,7 @@ use insta::assert_snapshot;
23use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; 23use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
24use ra_syntax::{ 24use ra_syntax::{
25 algo, 25 algo,
26 ast::{self, AstNode, AstToken}, 26 ast::{self, AstNode},
27}; 27};
28use stdx::format_to; 28use stdx::format_to;
29 29
@@ -87,7 +87,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
87 } 87 }
88 Err(SyntheticSyntax) => continue, 88 Err(SyntheticSyntax) => continue,
89 }; 89 };
90 types.push((syntax_ptr, ty)); 90 types.push((syntax_ptr.clone(), ty));
91 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { 91 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) {
92 mismatches.push((syntax_ptr, mismatch)); 92 mismatches.push((syntax_ptr, mismatch));
93 } 93 }
@@ -101,7 +101,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
101 let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db)); 101 let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db));
102 102
103 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { 103 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
104 (self_param.self_kw_token().unwrap().syntax().text_range(), "self".to_string()) 104 (self_param.self_token().unwrap().text_range(), "self".to_string())
105 } else { 105 } else {
106 (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) 106 (src_ptr.value.range(), node.text().to_string().replace("\n", " "))
107 }; 107 };
@@ -349,3 +349,103 @@ fn no_such_field_with_feature_flag_diagnostics() {
349 349
350 assert_snapshot!(diagnostics, @r###""###); 350 assert_snapshot!(diagnostics, @r###""###);
351} 351}
352
353#[test]
354fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() {
355 let diagnostics = TestDB::with_files(
356 r#"
357 //- /lib.rs crate:foo cfg:feature=foo
358 struct S {
359 #[cfg(feature = "foo")]
360 foo: u32,
361 #[cfg(not(feature = "foo"))]
362 bar: u32,
363 }
364
365 impl S {
366 #[cfg(feature = "foo")]
367 fn new(foo: u32) -> Self {
368 Self { foo }
369 }
370 #[cfg(not(feature = "foo"))]
371 fn new(bar: u32) -> Self {
372 Self { bar }
373 }
374 }
375 "#,
376 )
377 .diagnostics()
378 .0;
379
380 assert_snapshot!(diagnostics, @r###""###);
381}
382
383#[test]
384fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() {
385 let diagnostics = TestDB::with_files(
386 r#"
387 //- /lib.rs crate:foo cfg:feature=foo
388 struct S {
389 #[cfg(feature = "foo")]
390 foo: u32,
391 #[cfg(not(feature = "foo"))]
392 bar: u32,
393 }
394
395 impl S {
396 fn new(val: u32) -> Self {
397 Self {
398 #[cfg(feature = "foo")]
399 foo: val,
400 #[cfg(not(feature = "foo"))]
401 bar: val,
402 }
403 }
404 }
405 "#,
406 )
407 .diagnostics()
408 .0;
409
410 assert_snapshot!(diagnostics, @r###""###);
411}
412
413#[test]
414fn missing_record_pat_field_diagnostic() {
415 let diagnostics = TestDB::with_files(
416 r"
417 //- /lib.rs
418 struct S { foo: i32, bar: () }
419 fn baz(s: S) {
420 let S { foo: _ } = s;
421 }
422 ",
423 )
424 .diagnostics()
425 .0;
426
427 assert_snapshot!(diagnostics, @r###"
428 "{ foo: _ }": Missing structure fields:
429 - bar
430 "###
431 );
432}
433
434#[test]
435fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
436 let diagnostics = TestDB::with_files(
437 r"
438 //- /lib.rs
439 struct S { foo: i32, bar: () }
440 fn baz(s: S) -> i32 {
441 match s {
442 S { foo, .. } => foo,
443 }
444 }
445 ",
446 )
447 .diagnostics()
448 .0;
449
450 assert_snapshot!(diagnostics, @"");
451}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index ff4599b71..f2a9b1c40 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -1,10 +1,13 @@
1use std::fs;
2
1use insta::assert_snapshot; 3use insta::assert_snapshot;
2use ra_db::fixture::WithFixture; 4use ra_db::fixture::WithFixture;
3 5use test_utils::project_dir;
4use super::{infer, type_at, type_at_pos};
5 6
6use crate::test_db::TestDB; 7use crate::test_db::TestDB;
7 8
9use super::{infer, type_at, type_at_pos};
10
8#[test] 11#[test]
9fn cfg_impl_def() { 12fn cfg_impl_def() {
10 let (db, pos) = TestDB::with_position( 13 let (db, pos) = TestDB::with_position(
@@ -482,6 +485,30 @@ fn bar() -> u32 {0}
482} 485}
483 486
484#[test] 487#[test]
488#[ignore]
489fn include_accidentally_quadratic() {
490 let file = project_dir().join("crates/ra_syntax/test_data/accidentally_quadratic");
491 let big_file = fs::read_to_string(file).unwrap();
492 let big_file = vec![big_file; 10].join("\n");
493
494 let fixture = r#"
495//- /main.rs
496#[rustc_builtin_macro]
497macro_rules! include {() => {}}
498
499include!("foo.rs");
500
501fn main() {
502 RegisterBlock { }<|>;
503}
504 "#;
505 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file);
506
507 let (db, pos) = TestDB::with_position(&fixture);
508 assert_eq!("RegisterBlock", type_at_pos(&db, pos));
509}
510
511#[test]
485fn infer_builtin_macros_include_concat() { 512fn infer_builtin_macros_include_concat() {
486 let (db, pos) = TestDB::with_position( 513 let (db, pos) = TestDB::with_position(
487 r#" 514 r#"
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 5a1e12ce9..21e233379 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -177,7 +177,7 @@ fn solve(
177 177
178 let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); 178 let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL);
179 179
180 let solution = solver.solve_limited(&context, goal, || { 180 let should_continue = || {
181 context.db.check_canceled(); 181 context.db.check_canceled();
182 let remaining = fuel.get(); 182 let remaining = fuel.get();
183 fuel.set(remaining - 1); 183 fuel.set(remaining - 1);
@@ -185,12 +185,21 @@ fn solve(
185 log::debug!("fuel exhausted"); 185 log::debug!("fuel exhausted");
186 } 186 }
187 remaining > 0 187 remaining > 0
188 }); 188 };
189 let mut solve = || solver.solve_limited(&context, goal, should_continue);
190 // don't set the TLS for Chalk unless Chalk debugging is active, to make
191 // extra sure we only use it for debugging
192 let solution =
193 if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() };
189 194
190 log::debug!("solve({:?}) => {:?}", goal, solution); 195 log::debug!("solve({:?}) => {:?}", goal, solution);
191 solution 196 solution
192} 197}
193 198
199fn is_chalk_debug() -> bool {
200 std::env::var("CHALK_DEBUG").is_ok()
201}
202
194fn solution_from_chalk( 203fn solution_from_chalk(
195 db: &dyn HirDatabase, 204 db: &dyn HirDatabase,
196 solution: chalk_solve::Solution<Interner>, 205 solution: chalk_solve::Solution<Interner>,
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 1bc0f0713..c5f1b5232 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -20,6 +20,8 @@ use crate::{
20 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 20 ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
21}; 21};
22 22
23pub(super) mod tls;
24
23#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 25#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
24pub struct Interner; 26pub struct Interner;
25 27
@@ -33,90 +35,85 @@ impl chalk_ir::interner::Interner for Interner {
33 type Identifier = TypeAliasId; 35 type Identifier = TypeAliasId;
34 type DefId = InternId; 36 type DefId = InternId;
35 37
36 // FIXME: implement these
37 fn debug_struct_id( 38 fn debug_struct_id(
38 _type_kind_id: chalk_ir::StructId<Self>, 39 type_kind_id: StructId,
39 _fmt: &mut fmt::Formatter<'_>, 40 fmt: &mut fmt::Formatter<'_>,
40 ) -> Option<fmt::Result> { 41 ) -> Option<fmt::Result> {
41 None 42 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
42 } 43 }
43 44
44 fn debug_trait_id( 45 fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
45 _type_kind_id: chalk_ir::TraitId<Self>, 46 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
46 _fmt: &mut fmt::Formatter<'_>,
47 ) -> Option<fmt::Result> {
48 None
49 } 47 }
50 48
51 fn debug_assoc_type_id( 49 fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
52 _id: chalk_ir::AssocTypeId<Self>, 50 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
53 _fmt: &mut fmt::Formatter<'_>,
54 ) -> Option<fmt::Result> {
55 None
56 } 51 }
57 52
58 fn debug_alias( 53 fn debug_alias(
59 _projection: &chalk_ir::AliasTy<Self>, 54 alias: &chalk_ir::AliasTy<Interner>,
60 _fmt: &mut fmt::Formatter<'_>, 55 fmt: &mut fmt::Formatter<'_>,
61 ) -> Option<fmt::Result> { 56 ) -> Option<fmt::Result> {
62 None 57 tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt)))
63 } 58 }
64 59
65 fn debug_ty(_ty: &chalk_ir::Ty<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 60 fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
66 None 61 tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt)))
67 } 62 }
68 63
69 fn debug_lifetime( 64 fn debug_lifetime(
70 _lifetime: &chalk_ir::Lifetime<Self>, 65 lifetime: &chalk_ir::Lifetime<Interner>,
71 _fmt: &mut fmt::Formatter<'_>, 66 fmt: &mut fmt::Formatter<'_>,
72 ) -> Option<fmt::Result> { 67 ) -> Option<fmt::Result> {
73 None 68 tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt)))
74 } 69 }
75 70
76 fn debug_parameter( 71 fn debug_parameter(
77 _parameter: &Parameter<Self>, 72 parameter: &Parameter<Interner>,
78 _fmt: &mut fmt::Formatter<'_>, 73 fmt: &mut fmt::Formatter<'_>,
79 ) -> Option<fmt::Result> { 74 ) -> Option<fmt::Result> {
80 None 75 tls::with_current_program(|prog| Some(prog?.debug_parameter(parameter, fmt)))
81 } 76 }
82 77
83 fn debug_goal(_goal: &Goal<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 78 fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
84 None 79 tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt)))
85 } 80 }
86 81
87 fn debug_goals( 82 fn debug_goals(
88 _goals: &chalk_ir::Goals<Self>, 83 goals: &chalk_ir::Goals<Interner>,
89 _fmt: &mut fmt::Formatter<'_>, 84 fmt: &mut fmt::Formatter<'_>,
90 ) -> Option<fmt::Result> { 85 ) -> Option<fmt::Result> {
91 None 86 tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt)))
92 } 87 }
93 88
94 fn debug_program_clause_implication( 89 fn debug_program_clause_implication(
95 _pci: &chalk_ir::ProgramClauseImplication<Self>, 90 pci: &chalk_ir::ProgramClauseImplication<Interner>,
96 _fmt: &mut fmt::Formatter<'_>, 91 fmt: &mut fmt::Formatter<'_>,
97 ) -> Option<fmt::Result> { 92 ) -> Option<fmt::Result> {
98 None 93 tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt)))
99 } 94 }
100 95
101 fn debug_application_ty( 96 fn debug_application_ty(
102 _application_ty: &chalk_ir::ApplicationTy<Self>, 97 application_ty: &chalk_ir::ApplicationTy<Interner>,
103 _fmt: &mut fmt::Formatter<'_>, 98 fmt: &mut fmt::Formatter<'_>,
104 ) -> Option<fmt::Result> { 99 ) -> Option<fmt::Result> {
105 None 100 tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt)))
106 } 101 }
107 102
108 fn debug_substitution( 103 fn debug_substitution(
109 _substitution: &chalk_ir::Substitution<Self>, 104 substitution: &chalk_ir::Substitution<Interner>,
110 _fmt: &mut fmt::Formatter<'_>, 105 fmt: &mut fmt::Formatter<'_>,
111 ) -> Option<fmt::Result> { 106 ) -> Option<fmt::Result> {
112 None 107 tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt)))
113 } 108 }
114 109
115 fn debug_separator_trait_ref( 110 fn debug_separator_trait_ref(
116 _separator_trait_ref: &chalk_ir::SeparatorTraitRef<Self>, 111 separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
117 _fmt: &mut fmt::Formatter<'_>, 112 fmt: &mut fmt::Formatter<'_>,
118 ) -> Option<fmt::Result> { 113 ) -> Option<fmt::Result> {
119 None 114 tls::with_current_program(|prog| {
115 Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt))
116 })
120 } 117 }
121 118
122 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { 119 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs
new file mode 100644
index 000000000..d9bbb54a5
--- /dev/null
+++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs
@@ -0,0 +1,231 @@
1//! Implementation of Chalk debug helper functions using TLS.
2use std::fmt;
3
4use chalk_ir::{AliasTy, Goal, Goals, Lifetime, Parameter, ProgramClauseImplication, TypeName};
5
6use super::{from_chalk, Interner};
7use crate::{db::HirDatabase, CallableDef, TypeCtor};
8use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId};
9
10pub use unsafe_tls::{set_current_program, with_current_program};
11
12pub struct DebugContext<'a>(&'a (dyn HirDatabase + 'a));
13
14impl DebugContext<'_> {
15 pub fn debug_struct_id(
16 &self,
17 id: super::StructId,
18 f: &mut fmt::Formatter<'_>,
19 ) -> Result<(), fmt::Error> {
20 let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Struct(id));
21 match type_ctor {
22 TypeCtor::Bool => write!(f, "bool")?,
23 TypeCtor::Char => write!(f, "char")?,
24 TypeCtor::Int(t) => write!(f, "{}", t)?,
25 TypeCtor::Float(t) => write!(f, "{}", t)?,
26 TypeCtor::Str => write!(f, "str")?,
27 TypeCtor::Slice => write!(f, "slice")?,
28 TypeCtor::Array => write!(f, "array")?,
29 TypeCtor::RawPtr(m) => write!(f, "*{}", m.as_keyword_for_ptr())?,
30 TypeCtor::Ref(m) => write!(f, "&{}", m.as_keyword_for_ref())?,
31 TypeCtor::Never => write!(f, "!")?,
32 TypeCtor::Tuple { .. } => {
33 write!(f, "()")?;
34 }
35 TypeCtor::FnPtr { .. } => {
36 write!(f, "fn")?;
37 }
38 TypeCtor::FnDef(def) => {
39 let name = match def {
40 CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(),
41 CallableDef::StructId(s) => self.0.struct_data(s).name.clone(),
42 CallableDef::EnumVariantId(e) => {
43 let enum_data = self.0.enum_data(e.parent);
44 enum_data.variants[e.local_id].name.clone()
45 }
46 };
47 match def {
48 CallableDef::FunctionId(_) => write!(f, "{{fn {}}}", name)?,
49 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {
50 write!(f, "{{ctor {}}}", name)?
51 }
52 }
53 }
54 TypeCtor::Adt(def_id) => {
55 let name = match def_id {
56 AdtId::StructId(it) => self.0.struct_data(it).name.clone(),
57 AdtId::UnionId(it) => self.0.union_data(it).name.clone(),
58 AdtId::EnumId(it) => self.0.enum_data(it).name.clone(),
59 };
60 write!(f, "{}", name)?;
61 }
62 TypeCtor::AssociatedType(type_alias) => {
63 let trait_ = match type_alias.lookup(self.0.upcast()).container {
64 AssocContainerId::TraitId(it) => it,
65 _ => panic!("not an associated type"),
66 };
67 let trait_name = self.0.trait_data(trait_).name.clone();
68 let name = self.0.type_alias_data(type_alias).name.clone();
69 write!(f, "{}::{}", trait_name, name)?;
70 }
71 TypeCtor::Closure { def, expr } => {
72 write!(f, "{{closure {:?} in {:?}}}", expr.into_raw(), def)?;
73 }
74 }
75 Ok(())
76 }
77
78 pub fn debug_trait_id(
79 &self,
80 id: super::TraitId,
81 fmt: &mut fmt::Formatter<'_>,
82 ) -> Result<(), fmt::Error> {
83 let trait_: hir_def::TraitId = from_chalk(self.0, id);
84 let trait_data = self.0.trait_data(trait_);
85 write!(fmt, "{}", trait_data.name)
86 }
87
88 pub fn debug_assoc_type_id(
89 &self,
90 id: super::AssocTypeId,
91 fmt: &mut fmt::Formatter<'_>,
92 ) -> Result<(), fmt::Error> {
93 let type_alias: TypeAliasId = from_chalk(self.0, id);
94 let type_alias_data = self.0.type_alias_data(type_alias);
95 let trait_ = match type_alias.lookup(self.0.upcast()).container {
96 AssocContainerId::TraitId(t) => t,
97 _ => panic!("associated type not in trait"),
98 };
99 let trait_data = self.0.trait_data(trait_);
100 write!(fmt, "{}::{}", trait_data.name, type_alias_data.name)
101 }
102
103 pub fn debug_alias(
104 &self,
105 alias: &AliasTy<Interner>,
106 fmt: &mut fmt::Formatter<'_>,
107 ) -> Result<(), fmt::Error> {
108 let type_alias: TypeAliasId = from_chalk(self.0, alias.associated_ty_id);
109 let type_alias_data = self.0.type_alias_data(type_alias);
110 let trait_ = match type_alias.lookup(self.0.upcast()).container {
111 AssocContainerId::TraitId(t) => t,
112 _ => panic!("associated type not in trait"),
113 };
114 let trait_data = self.0.trait_data(trait_);
115 let params = alias.substitution.parameters(&Interner);
116 write!(
117 fmt,
118 "<{:?} as {}<{:?}>>::{}",
119 &params[0],
120 trait_data.name,
121 &params[1..],
122 type_alias_data.name
123 )
124 }
125
126 pub fn debug_ty(
127 &self,
128 ty: &chalk_ir::Ty<Interner>,
129 fmt: &mut fmt::Formatter<'_>,
130 ) -> Result<(), fmt::Error> {
131 write!(fmt, "{:?}", ty.data(&Interner))
132 }
133
134 pub fn debug_lifetime(
135 &self,
136 lifetime: &Lifetime<Interner>,
137 fmt: &mut fmt::Formatter<'_>,
138 ) -> Result<(), fmt::Error> {
139 write!(fmt, "{:?}", lifetime.data(&Interner))
140 }
141
142 pub fn debug_parameter(
143 &self,
144 parameter: &Parameter<Interner>,
145 fmt: &mut fmt::Formatter<'_>,
146 ) -> Result<(), fmt::Error> {
147 write!(fmt, "{:?}", parameter.data(&Interner).inner_debug())
148 }
149
150 pub fn debug_goal(
151 &self,
152 goal: &Goal<Interner>,
153 fmt: &mut fmt::Formatter<'_>,
154 ) -> Result<(), fmt::Error> {
155 let goal_data = goal.data(&Interner);
156 write!(fmt, "{:?}", goal_data)
157 }
158
159 pub fn debug_goals(
160 &self,
161 goals: &Goals<Interner>,
162 fmt: &mut fmt::Formatter<'_>,
163 ) -> Result<(), fmt::Error> {
164 write!(fmt, "{:?}", goals.debug(&Interner))
165 }
166
167 pub fn debug_program_clause_implication(
168 &self,
169 pci: &ProgramClauseImplication<Interner>,
170 fmt: &mut fmt::Formatter<'_>,
171 ) -> Result<(), fmt::Error> {
172 write!(fmt, "{:?}", pci.debug(&Interner))
173 }
174
175 pub fn debug_application_ty(
176 &self,
177 application_ty: &chalk_ir::ApplicationTy<Interner>,
178 fmt: &mut fmt::Formatter<'_>,
179 ) -> Result<(), fmt::Error> {
180 write!(fmt, "{:?}", application_ty.debug(&Interner))
181 }
182
183 pub fn debug_substitution(
184 &self,
185 substitution: &chalk_ir::Substitution<Interner>,
186 fmt: &mut fmt::Formatter<'_>,
187 ) -> Result<(), fmt::Error> {
188 write!(fmt, "{:?}", substitution.debug(&Interner))
189 }
190
191 pub fn debug_separator_trait_ref(
192 &self,
193 separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
194 fmt: &mut fmt::Formatter<'_>,
195 ) -> Result<(), fmt::Error> {
196 write!(fmt, "{:?}", separator_trait_ref.debug(&Interner))
197 }
198}
199
200mod unsafe_tls {
201 use super::DebugContext;
202 use crate::db::HirDatabase;
203 use scoped_tls::scoped_thread_local;
204
205 scoped_thread_local!(static PROGRAM: DebugContext);
206
207 pub fn with_current_program<R>(
208 op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R,
209 ) -> R {
210 if PROGRAM.is_set() {
211 PROGRAM.with(|prog| op(Some(prog)))
212 } else {
213 op(None)
214 }
215 }
216
217 pub fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R
218 where
219 OP: FnOnce() -> R,
220 {
221 let ctx = DebugContext(p);
222 // we're transmuting the lifetime in the DebugContext to static. This is
223 // fine because we only keep the reference for the lifetime of this
224 // function, *and* the only way to access the context is through
225 // `with_current_program`, which hides the lifetime through the `for`
226 // type.
227 let static_p: &DebugContext<'static> =
228 unsafe { std::mem::transmute::<&DebugContext, &DebugContext<'static>>(&ctx) };
229 PROGRAM.set(static_p, || op())
230 }
231}
diff --git a/crates/ra_ide/src/completion/complete_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs
index 62ae5ccb4..f84b559fc 100644
--- a/crates/ra_ide/src/completion/complete_fn_param.rs
+++ b/crates/ra_ide/src/completion/complete_fn_param.rs
@@ -1,6 +1,9 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_syntax::{ast, match_ast, AstNode}; 3use ra_syntax::{
4 ast::{self, ModuleItemOwner},
5 match_ast, AstNode,
6};
4use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
5 8
6use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; 9use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions};
@@ -16,11 +19,19 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
16 19
17 let mut params = FxHashMap::default(); 20 let mut params = FxHashMap::default();
18 for node in ctx.token.parent().ancestors() { 21 for node in ctx.token.parent().ancestors() {
19 match_ast! { 22 let items = match_ast! {
20 match node { 23 match node {
21 ast::SourceFile(it) => process(it, &mut params), 24 ast::SourceFile(it) => it.items(),
22 ast::ItemList(it) => process(it, &mut params), 25 ast::ItemList(it) => it.items(),
23 _ => (), 26 _ => continue,
27 }
28 };
29 for item in items {
30 if let ast::ModuleItem::FnDef(func) = item {
31 func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
32 let text = param.syntax().text().to_string();
33 params.entry(text).or_insert((0, param)).0 += 1;
34 })
24 } 35 }
25 } 36 }
26 } 37 }
@@ -39,15 +50,6 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
39 .lookup_by(lookup) 50 .lookup_by(lookup)
40 .add_to(acc) 51 .add_to(acc)
41 }); 52 });
42
43 fn process<N: ast::FnDefOwner>(node: N, params: &mut FxHashMap<String, (u32, ast::Param)>) {
44 node.functions().filter_map(|it| it.param_list()).flat_map(|it| it.params()).for_each(
45 |param| {
46 let text = param.syntax().text().to_string();
47 params.entry(text).or_insert((0, param)).0 += 1;
48 },
49 )
50 }
51} 53}
52 54
53#[cfg(test)] 55#[cfg(test)]
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs
index ded1ff3bc..fab02945c 100644
--- a/crates/ra_ide/src/completion/complete_trait_impl.rs
+++ b/crates/ra_ide/src/completion/complete_trait_impl.rs
@@ -35,7 +35,7 @@ use hir::{self, Docs, HasSource};
35use ra_assists::utils::get_missing_impl_items; 35use ra_assists::utils::get_missing_impl_items;
36use ra_syntax::{ 36use ra_syntax::{
37 ast::{self, edit, ImplDef}, 37 ast::{self, edit, ImplDef},
38 AstNode, SyntaxKind, SyntaxNode, TextRange, 38 AstNode, SyntaxKind, SyntaxNode, TextRange, T,
39}; 39};
40use ra_text_edit::TextEdit; 40use ra_text_edit::TextEdit;
41 41
@@ -204,7 +204,7 @@ fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
204 let end = const_ 204 let end = const_
205 .syntax() 205 .syntax()
206 .children_with_tokens() 206 .children_with_tokens()
207 .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ) 207 .find(|s| s.kind() == T![;] || s.kind() == T![=])
208 .map_or(const_end, |f| f.text_range().start()); 208 .map_or(const_end, |f| f.text_range().start());
209 209
210 let len = end - start; 210 let len = end - start;
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 0e34d85db..6637afaf7 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -191,8 +191,8 @@ impl<'a> CompletionContext<'a> {
191 if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { 191 if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) {
192 self.is_pat_binding_or_const = true; 192 self.is_pat_binding_or_const = true;
193 if bind_pat.at_token().is_some() 193 if bind_pat.at_token().is_some()
194 || bind_pat.ref_kw_token().is_some() 194 || bind_pat.ref_token().is_some()
195 || bind_pat.mut_kw_token().is_some() 195 || bind_pat.mut_token().is_some()
196 { 196 {
197 self.is_pat_binding_or_const = false; 197 self.is_pat_binding_or_const = false;
198 } 198 }
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 4b133b19b..da9f55a69 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! This module defines multiple types of inlay hints and their visibility
2 2
3use hir::{Adt, HirDisplay, Semantics, Type}; 3use hir::{Adt, HirDisplay, Semantics, Type};
4use ra_ide_db::RootDatabase; 4use ra_ide_db::RootDatabase;
@@ -235,8 +235,7 @@ fn should_show_param_hint(
235 param_name: &str, 235 param_name: &str,
236 argument: &ast::Expr, 236 argument: &ast::Expr,
237) -> bool { 237) -> bool {
238 let argument_string = argument.syntax().to_string(); 238 if param_name.is_empty() || is_argument_similar_to_param(argument, param_name) {
239 if param_name.is_empty() || argument_string.ends_with(param_name) {
240 return false; 239 return false;
241 } 240 }
242 241
@@ -245,14 +244,37 @@ fn should_show_param_hint(
245 } else { 244 } else {
246 fn_signature.parameters.len() 245 fn_signature.parameters.len()
247 }; 246 };
247
248 // avoid displaying hints for common functions like map, filter, etc. 248 // avoid displaying hints for common functions like map, filter, etc.
249 if parameters_len == 1 && (param_name.len() == 1 || param_name == "predicate") { 249 // or other obvious words used in std
250 if parameters_len == 1 && is_obvious_param(param_name) {
250 return false; 251 return false;
251 } 252 }
252
253 true 253 true
254} 254}
255 255
256fn is_argument_similar_to_param(argument: &ast::Expr, param_name: &str) -> bool {
257 let argument_string = remove_ref(argument.clone()).syntax().to_string();
258 argument_string.starts_with(&param_name) || argument_string.ends_with(&param_name)
259}
260
261fn remove_ref(expr: ast::Expr) -> ast::Expr {
262 if let ast::Expr::RefExpr(ref_expr) = &expr {
263 if let Some(inner) = ref_expr.expr() {
264 return inner;
265 }
266 }
267 expr
268}
269
270fn is_obvious_param(param_name: &str) -> bool {
271 let is_obvious_param_name = match param_name {
272 "predicate" | "value" | "pat" | "rhs" | "other" => true,
273 _ => false,
274 };
275 param_name.len() == 1 || is_obvious_param_name
276}
277
256fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> { 278fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> {
257 match expr { 279 match expr {
258 ast::Expr::CallExpr(expr) => { 280 ast::Expr::CallExpr(expr) => {
@@ -1059,9 +1081,18 @@ impl Test {
1059 self 1081 self
1060 } 1082 }
1061 1083
1084 fn field(self, value: i32) -> Self {
1085 self
1086 }
1087
1062 fn no_hints_expected(&self, _: i32, test_var: i32) {} 1088 fn no_hints_expected(&self, _: i32, test_var: i32) {}
1063} 1089}
1064 1090
1091struct Param {}
1092
1093fn different_order(param: &Param) {}
1094fn different_order_mut(param: &mut Param) {}
1095
1065fn main() { 1096fn main() {
1066 let container: TestVarContainer = TestVarContainer { test_var: 42 }; 1097 let container: TestVarContainer = TestVarContainer { test_var: 42 };
1067 let test: Test = Test {}; 1098 let test: Test = Test {};
@@ -1069,11 +1100,20 @@ fn main() {
1069 map(22); 1100 map(22);
1070 filter(33); 1101 filter(33);
1071 1102
1072 let test_processed: Test = test.map(1).filter(2); 1103 let test_processed: Test = test.map(1).filter(2).field(3);
1073 1104
1074 let test_var: i32 = 55; 1105 let test_var: i32 = 55;
1075 test_processed.no_hints_expected(22, test_var); 1106 test_processed.no_hints_expected(22, test_var);
1076 test_processed.no_hints_expected(33, container.test_var); 1107 test_processed.no_hints_expected(33, container.test_var);
1108
1109 let param_begin: Param = Param {};
1110 different_order(&param_begin);
1111 different_order(&mut param_begin);
1112
1113 let a: f64 = 7.0;
1114 let b: f64 = 4.0;
1115 let _: f64 = a.div_euclid(b);
1116 let _: f64 = a.abs_sub(b);
1077}"#, 1117}"#,
1078 ); 1118 );
1079 1119
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index ad6fd50aa..7d0544ff4 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -152,7 +152,7 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio
152 if stmt.initializer().is_some() { 152 if stmt.initializer().is_some() {
153 let pat = stmt.pat()?; 153 let pat = stmt.pat()?;
154 if let ast::Pat::BindPat(it) = pat { 154 if let ast::Pat::BindPat(it) = pat {
155 if it.mut_kw_token().is_some() { 155 if it.mut_token().is_some() {
156 return Some(ReferenceAccess::Write); 156 return Some(ReferenceAccess::Write);
157 } 157 }
158 } 158 }
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs
index f58e436d1..5842ae2e8 100644
--- a/crates/ra_ide/src/syntax_tree.rs
+++ b/crates/ra_ide/src/syntax_tree.rs
@@ -165,7 +165,7 @@ SOURCE_FILE@[0; 60)
165 PATH_SEGMENT@[16; 22) 165 PATH_SEGMENT@[16; 22)
166 NAME_REF@[16; 22) 166 NAME_REF@[16; 22)
167 IDENT@[16; 22) "assert" 167 IDENT@[16; 22) "assert"
168 EXCL@[22; 23) "!" 168 BANG@[22; 23) "!"
169 TOKEN_TREE@[23; 57) 169 TOKEN_TREE@[23; 57)
170 L_PAREN@[23; 24) "(" 170 L_PAREN@[23; 24) "("
171 STRING@[24; 52) "\"\n fn foo() {\n ..." 171 STRING@[24; 52) "\"\n fn foo() {\n ..."
@@ -173,7 +173,7 @@ SOURCE_FILE@[0; 60)
173 WHITESPACE@[53; 54) " " 173 WHITESPACE@[53; 54) " "
174 STRING@[54; 56) "\"\"" 174 STRING@[54; 56) "\"\""
175 R_PAREN@[56; 57) ")" 175 R_PAREN@[56; 57) ")"
176 SEMI@[57; 58) ";" 176 SEMICOLON@[57; 58) ";"
177 WHITESPACE@[58; 59) "\n" 177 WHITESPACE@[58; 59) "\n"
178 R_CURLY@[59; 60) "}" 178 R_CURLY@[59; 60) "}"
179"# 179"#
@@ -226,7 +226,7 @@ EXPR_STMT@[16; 58)
226 PATH_SEGMENT@[16; 22) 226 PATH_SEGMENT@[16; 22)
227 NAME_REF@[16; 22) 227 NAME_REF@[16; 22)
228 IDENT@[16; 22) "assert" 228 IDENT@[16; 22) "assert"
229 EXCL@[22; 23) "!" 229 BANG@[22; 23) "!"
230 TOKEN_TREE@[23; 57) 230 TOKEN_TREE@[23; 57)
231 L_PAREN@[23; 24) "(" 231 L_PAREN@[23; 24) "("
232 STRING@[24; 52) "\"\n fn foo() {\n ..." 232 STRING@[24; 52) "\"\n fn foo() {\n ..."
@@ -234,7 +234,7 @@ EXPR_STMT@[16; 58)
234 WHITESPACE@[53; 54) " " 234 WHITESPACE@[53; 54) " "
235 STRING@[54; 56) "\"\"" 235 STRING@[54; 56) "\"\""
236 R_PAREN@[56; 57) ")" 236 R_PAREN@[56; 57) ")"
237 SEMI@[57; 58) ";" 237 SEMICOLON@[57; 58) ";"
238"# 238"#
239 .trim() 239 .trim()
240 ); 240 );
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs
index 71d2bcb04..f55cd3bf5 100644
--- a/crates/ra_ide/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
@@ -63,7 +63,7 @@ fn on_char_typed_inner(
63fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> { 63fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> {
64 assert_eq!(file.syntax().text().char_at(offset), Some('=')); 64 assert_eq!(file.syntax().text().char_at(offset), Some('='));
65 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; 65 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
66 if let_stmt.semi_token().is_some() { 66 if let_stmt.semicolon_token().is_some() {
67 return None; 67 return None;
68 } 68 }
69 if let Some(expr) = let_stmt.initializer() { 69 if let Some(expr) = let_stmt.initializer() {
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 8e8ae2b29..9fb5cb058 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -137,21 +137,23 @@ impl TokenMap {
137 token_id: tt::TokenId, 137 token_id: tt::TokenId,
138 open_relative_range: TextRange, 138 open_relative_range: TextRange,
139 close_relative_range: TextRange, 139 close_relative_range: TextRange,
140 ) { 140 ) -> usize {
141 let res = self.entries.len();
141 self.entries 142 self.entries
142 .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range))); 143 .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range)));
144 res
143 } 145 }
144 146
145 fn update_close_delim(&mut self, token_id: tt::TokenId, close_relative_range: TextRange) { 147 fn update_close_delim(&mut self, idx: usize, close_relative_range: TextRange) {
146 if let Some(entry) = self.entries.iter_mut().find(|(tid, _)| *tid == token_id) { 148 let (_, token_text_range) = &mut self.entries[idx];
147 if let TokenTextRange::Delimiter(dim, _) = entry.1 { 149 if let TokenTextRange::Delimiter(dim, _) = token_text_range {
148 entry.1 = TokenTextRange::Delimiter(dim, close_relative_range); 150 *token_text_range = TokenTextRange::Delimiter(*dim, close_relative_range);
149 }
150 } 151 }
151 } 152 }
152 153
153 fn remove_delim(&mut self, token_id: tt::TokenId) { 154 fn remove_delim(&mut self, idx: usize) {
154 self.entries.retain(|(tid, _)| *tid != token_id); 155 // FIXME: This could be accidently quadratic
156 self.entries.remove(idx);
155 } 157 }
156} 158}
157 159
@@ -238,24 +240,24 @@ impl TokenIdAlloc {
238 token_id 240 token_id
239 } 241 }
240 242
241 fn open_delim(&mut self, open_abs_range: TextRange) -> tt::TokenId { 243 fn open_delim(&mut self, open_abs_range: TextRange) -> (tt::TokenId, usize) {
242 let token_id = tt::TokenId(self.next_id); 244 let token_id = tt::TokenId(self.next_id);
243 self.next_id += 1; 245 self.next_id += 1;
244 self.map.insert_delim( 246 let idx = self.map.insert_delim(
245 token_id, 247 token_id,
246 open_abs_range - self.global_offset, 248 open_abs_range - self.global_offset,
247 open_abs_range - self.global_offset, 249 open_abs_range - self.global_offset,
248 ); 250 );
249 token_id 251 (token_id, idx)
250 } 252 }
251 253
252 fn close_delim(&mut self, id: tt::TokenId, close_abs_range: Option<TextRange>) { 254 fn close_delim(&mut self, idx: usize, close_abs_range: Option<TextRange>) {
253 match close_abs_range { 255 match close_abs_range {
254 None => { 256 None => {
255 self.map.remove_delim(id); 257 self.map.remove_delim(idx);
256 } 258 }
257 Some(close) => { 259 Some(close) => {
258 self.map.update_close_delim(id, close - self.global_offset); 260 self.map.update_close_delim(idx, close - self.global_offset);
259 } 261 }
260 } 262 }
261 } 263 }
@@ -322,7 +324,7 @@ trait TokenConvertor {
322 324
323 if let Some((kind, closed)) = delim { 325 if let Some((kind, closed)) = delim {
324 let mut subtree = tt::Subtree::default(); 326 let mut subtree = tt::Subtree::default();
325 let id = self.id_alloc().open_delim(range); 327 let (id, idx) = self.id_alloc().open_delim(range);
326 subtree.delimiter = Some(tt::Delimiter { kind, id }); 328 subtree.delimiter = Some(tt::Delimiter { kind, id });
327 329
328 while self.peek().map(|it| it.kind() != closed).unwrap_or(false) { 330 while self.peek().map(|it| it.kind() != closed).unwrap_or(false) {
@@ -331,7 +333,7 @@ trait TokenConvertor {
331 let last_range = match self.bump() { 333 let last_range = match self.bump() {
332 None => { 334 None => {
333 // For error resilience, we insert an char punct for the opening delim here 335 // For error resilience, we insert an char punct for the opening delim here
334 self.id_alloc().close_delim(id, None); 336 self.id_alloc().close_delim(idx, None);
335 let leaf: tt::Leaf = tt::Punct { 337 let leaf: tt::Leaf = tt::Punct {
336 id: self.id_alloc().alloc(range), 338 id: self.id_alloc().alloc(range),
337 char: token.to_char().unwrap(), 339 char: token.to_char().unwrap(),
@@ -344,7 +346,7 @@ trait TokenConvertor {
344 } 346 }
345 Some(it) => it.1, 347 Some(it) => it.1,
346 }; 348 };
347 self.id_alloc().close_delim(id, Some(last_range)); 349 self.id_alloc().close_delim(idx, Some(last_range));
348 subtree.into() 350 subtree.into()
349 } else { 351 } else {
350 let spacing = match self.peek() { 352 let spacing = match self.peek() {
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 1ef6f6eed..5d1274d21 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -252,7 +252,7 @@ fn test_expr_order() {
252 STAR@[11; 12) "*" 252 STAR@[11; 12) "*"
253 LITERAL@[12; 13) 253 LITERAL@[12; 13)
254 INT_NUMBER@[12; 13) "2" 254 INT_NUMBER@[12; 13) "2"
255 SEMI@[13; 14) ";" 255 SEMICOLON@[13; 14) ";"
256 R_CURLY@[14; 15) "}""#, 256 R_CURLY@[14; 15) "}""#,
257 ); 257 );
258} 258}
@@ -605,7 +605,7 @@ fn test_tt_to_stmts() {
605 EQ@[4; 5) "=" 605 EQ@[4; 5) "="
606 LITERAL@[5; 6) 606 LITERAL@[5; 6)
607 INT_NUMBER@[5; 6) "0" 607 INT_NUMBER@[5; 6) "0"
608 SEMI@[6; 7) ";" 608 SEMICOLON@[6; 7) ";"
609 EXPR_STMT@[7; 14) 609 EXPR_STMT@[7; 14)
610 BIN_EXPR@[7; 13) 610 BIN_EXPR@[7; 13)
611 PATH_EXPR@[7; 8) 611 PATH_EXPR@[7; 8)
@@ -620,7 +620,7 @@ fn test_tt_to_stmts() {
620 PLUS@[11; 12) "+" 620 PLUS@[11; 12) "+"
621 LITERAL@[12; 13) 621 LITERAL@[12; 13)
622 INT_NUMBER@[12; 13) "1" 622 INT_NUMBER@[12; 13) "1"
623 SEMI@[13; 14) ";" 623 SEMICOLON@[13; 14) ";"
624 EXPR_STMT@[14; 15) 624 EXPR_STMT@[14; 15)
625 PATH_EXPR@[14; 15) 625 PATH_EXPR@[14; 15)
626 PATH@[14; 15) 626 PATH@[14; 15)
@@ -953,7 +953,7 @@ fn test_tt_composite2() {
953 PATH_SEGMENT@[0; 3) 953 PATH_SEGMENT@[0; 3)
954 NAME_REF@[0; 3) 954 NAME_REF@[0; 3)
955 IDENT@[0; 3) "abs" 955 IDENT@[0; 3) "abs"
956 EXCL@[3; 4) "!" 956 BANG@[3; 4) "!"
957 TOKEN_TREE@[4; 10) 957 TOKEN_TREE@[4; 10)
958 L_PAREN@[4; 5) "(" 958 L_PAREN@[4; 5) "("
959 EQ@[5; 6) "=" 959 EQ@[5; 6) "="
@@ -1073,14 +1073,14 @@ fn test_vec() {
1073 PATH_SEGMENT@[9; 12) 1073 PATH_SEGMENT@[9; 12)
1074 NAME_REF@[9; 12) 1074 NAME_REF@[9; 12)
1075 IDENT@[9; 12) "Vec" 1075 IDENT@[9; 12) "Vec"
1076 COLONCOLON@[12; 14) "::" 1076 COLON2@[12; 14) "::"
1077 PATH_SEGMENT@[14; 17) 1077 PATH_SEGMENT@[14; 17)
1078 NAME_REF@[14; 17) 1078 NAME_REF@[14; 17)
1079 IDENT@[14; 17) "new" 1079 IDENT@[14; 17) "new"
1080 ARG_LIST@[17; 19) 1080 ARG_LIST@[17; 19)
1081 L_PAREN@[17; 18) "(" 1081 L_PAREN@[17; 18) "("
1082 R_PAREN@[18; 19) ")" 1082 R_PAREN@[18; 19) ")"
1083 SEMI@[19; 20) ";" 1083 SEMICOLON@[19; 20) ";"
1084 EXPR_STMT@[20; 33) 1084 EXPR_STMT@[20; 33)
1085 METHOD_CALL_EXPR@[20; 32) 1085 METHOD_CALL_EXPR@[20; 32)
1086 PATH_EXPR@[20; 21) 1086 PATH_EXPR@[20; 21)
@@ -1096,7 +1096,7 @@ fn test_vec() {
1096 LITERAL@[27; 31) 1096 LITERAL@[27; 31)
1097 INT_NUMBER@[27; 31) "1u32" 1097 INT_NUMBER@[27; 31) "1u32"
1098 R_PAREN@[31; 32) ")" 1098 R_PAREN@[31; 32) ")"
1099 SEMI@[32; 33) ";" 1099 SEMICOLON@[32; 33) ";"
1100 EXPR_STMT@[33; 43) 1100 EXPR_STMT@[33; 43)
1101 METHOD_CALL_EXPR@[33; 42) 1101 METHOD_CALL_EXPR@[33; 42)
1102 PATH_EXPR@[33; 34) 1102 PATH_EXPR@[33; 34)
@@ -1112,7 +1112,7 @@ fn test_vec() {
1112 LITERAL@[40; 41) 1112 LITERAL@[40; 41)
1113 INT_NUMBER@[40; 41) "2" 1113 INT_NUMBER@[40; 41) "2"
1114 R_PAREN@[41; 42) ")" 1114 R_PAREN@[41; 42) ")"
1115 SEMI@[42; 43) ";" 1115 SEMICOLON@[42; 43) ";"
1116 PATH_EXPR@[43; 44) 1116 PATH_EXPR@[43; 44)
1117 PATH@[43; 44) 1117 PATH@[43; 44)
1118 PATH_SEGMENT@[43; 44) 1118 PATH_SEGMENT@[43; 44)
@@ -1760,7 +1760,7 @@ fn test_no_space_after_semi_colon() {
1760 MOD_KW@[21; 24) "mod" 1760 MOD_KW@[21; 24) "mod"
1761 NAME@[24; 25) 1761 NAME@[24; 25)
1762 IDENT@[24; 25) "m" 1762 IDENT@[24; 25) "m"
1763 SEMI@[25; 26) ";" 1763 SEMICOLON@[25; 26) ";"
1764 MODULE@[26; 52) 1764 MODULE@[26; 52)
1765 ATTR@[26; 47) 1765 ATTR@[26; 47)
1766 POUND@[26; 27) "#" 1766 POUND@[26; 27) "#"
@@ -1779,7 +1779,7 @@ fn test_no_space_after_semi_colon() {
1779 MOD_KW@[47; 50) "mod" 1779 MOD_KW@[47; 50) "mod"
1780 NAME@[50; 51) 1780 NAME@[50; 51)
1781 IDENT@[50; 51) "f" 1781 IDENT@[50; 51) "f"
1782 SEMI@[51; 52) ";""###, 1782 SEMICOLON@[51; 52) ";""###,
1783 ); 1783 );
1784} 1784}
1785 1785
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index c486c0211..a1bd53063 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -339,7 +339,8 @@ fn expr_bp(p: &mut Parser, mut r: Restrictions, bp: u8) -> (Option<CompletedMark
339 (Some(lhs), BlockLike::NotBlock) 339 (Some(lhs), BlockLike::NotBlock)
340} 340}
341 341
342const LHS_FIRST: TokenSet = atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOT, MINUS]); 342const LHS_FIRST: TokenSet =
343 atom::ATOM_EXPR_FIRST.union(token_set![T![&], T![*], T![!], T![.], T![-]]);
343 344
344fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { 345fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
345 let m; 346 let m;
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index 386969d2d..fe1a039cb 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -3,8 +3,19 @@
3use super::*; 3use super::*;
4 4
5pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![ 5pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![
6 L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW, 6 T!['('],
7 DYN_KW, L_ANGLE, 7 T!['['],
8 T![<],
9 T![!],
10 T![*],
11 T![&],
12 T![_],
13 T![fn],
14 T![unsafe],
15 T![extern],
16 T![for],
17 T![impl],
18 T![dyn],
8]); 19]);
9 20
10const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA, L_DOLLAR]; 21const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA, L_DOLLAR];
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 004f4e564..524e7d784 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -9,7 +9,7 @@ pub enum SyntaxKind {
9 TOMBSTONE, 9 TOMBSTONE,
10 #[doc(hidden)] 10 #[doc(hidden)]
11 EOF, 11 EOF,
12 SEMI, 12 SEMICOLON,
13 COMMA, 13 COMMA,
14 L_PAREN, 14 L_PAREN,
15 R_PAREN, 15 R_PAREN,
@@ -33,15 +33,15 @@ pub enum SyntaxKind {
33 PERCENT, 33 PERCENT,
34 UNDERSCORE, 34 UNDERSCORE,
35 DOT, 35 DOT,
36 DOTDOT, 36 DOT2,
37 DOTDOTDOT, 37 DOT3,
38 DOTDOTEQ, 38 DOT2EQ,
39 COLON, 39 COLON,
40 COLONCOLON, 40 COLON2,
41 EQ, 41 EQ,
42 EQEQ, 42 EQ2,
43 FAT_ARROW, 43 FAT_ARROW,
44 EXCL, 44 BANG,
45 NEQ, 45 NEQ,
46 MINUS, 46 MINUS,
47 THIN_ARROW, 47 THIN_ARROW,
@@ -55,8 +55,8 @@ pub enum SyntaxKind {
55 SLASHEQ, 55 SLASHEQ,
56 STAREQ, 56 STAREQ,
57 PERCENTEQ, 57 PERCENTEQ,
58 AMPAMP, 58 AMP2,
59 PIPEPIPE, 59 PIPE2,
60 SHL, 60 SHL,
61 SHR, 61 SHR,
62 SHLEQ, 62 SHLEQ,
@@ -265,12 +265,12 @@ impl SyntaxKind {
265 } 265 }
266 pub fn is_punct(self) -> bool { 266 pub fn is_punct(self) -> bool {
267 match self { 267 match self {
268 SEMI | COMMA | L_PAREN | R_PAREN | L_CURLY | R_CURLY | L_BRACK | R_BRACK | L_ANGLE 268 SEMICOLON | COMMA | L_PAREN | R_PAREN | L_CURLY | R_CURLY | L_BRACK | R_BRACK
269 | R_ANGLE | AT | POUND | TILDE | QUESTION | DOLLAR | AMP | PIPE | PLUS | STAR 269 | L_ANGLE | R_ANGLE | AT | POUND | TILDE | QUESTION | DOLLAR | AMP | PIPE | PLUS
270 | SLASH | CARET | PERCENT | UNDERSCORE | DOT | DOTDOT | DOTDOTDOT | DOTDOTEQ 270 | STAR | SLASH | CARET | PERCENT | UNDERSCORE | DOT | DOT2 | DOT3 | DOT2EQ | COLON
271 | COLON | COLONCOLON | EQ | EQEQ | FAT_ARROW | EXCL | NEQ | MINUS | THIN_ARROW 271 | COLON2 | EQ | EQ2 | FAT_ARROW | BANG | NEQ | MINUS | THIN_ARROW | LTEQ | GTEQ
272 | LTEQ | GTEQ | PLUSEQ | MINUSEQ | PIPEEQ | AMPEQ | CARETEQ | SLASHEQ | STAREQ 272 | PLUSEQ | MINUSEQ | PIPEEQ | AMPEQ | CARETEQ | SLASHEQ | STAREQ | PERCENTEQ | AMP2
273 | PERCENTEQ | AMPAMP | PIPEPIPE | SHL | SHR | SHLEQ | SHREQ => true, 273 | PIPE2 | SHL | SHR | SHLEQ | SHREQ => true,
274 _ => false, 274 _ => false,
275 } 275 }
276 } 276 }
@@ -329,7 +329,7 @@ impl SyntaxKind {
329 } 329 }
330 pub fn from_char(c: char) -> Option<SyntaxKind> { 330 pub fn from_char(c: char) -> Option<SyntaxKind> {
331 let tok = match c { 331 let tok = match c {
332 ';' => SEMI, 332 ';' => SEMICOLON,
333 ',' => COMMA, 333 ',' => COMMA,
334 '(' => L_PAREN, 334 '(' => L_PAREN,
335 ')' => R_PAREN, 335 ')' => R_PAREN,
@@ -355,7 +355,7 @@ impl SyntaxKind {
355 '.' => DOT, 355 '.' => DOT,
356 ':' => COLON, 356 ':' => COLON,
357 '=' => EQ, 357 '=' => EQ,
358 '!' => EXCL, 358 '!' => BANG,
359 '-' => MINUS, 359 '-' => MINUS,
360 _ => return None, 360 _ => return None,
361 }; 361 };
@@ -363,296 +363,4 @@ impl SyntaxKind {
363 } 363 }
364} 364}
365#[macro_export] 365#[macro_export]
366macro_rules! T { 366macro_rules ! T { [ ; ] => { $ crate :: SyntaxKind :: SEMICOLON } ; [ , ] => { $ crate :: SyntaxKind :: COMMA } ; [ '(' ] => { $ crate :: SyntaxKind :: L_PAREN } ; [ ')' ] => { $ crate :: SyntaxKind :: R_PAREN } ; [ '{' ] => { $ crate :: SyntaxKind :: L_CURLY } ; [ '}' ] => { $ crate :: SyntaxKind :: R_CURLY } ; [ '[' ] => { $ crate :: SyntaxKind :: L_BRACK } ; [ ']' ] => { $ crate :: SyntaxKind :: R_BRACK } ; [ < ] => { $ crate :: SyntaxKind :: L_ANGLE } ; [ > ] => { $ crate :: SyntaxKind :: R_ANGLE } ; [ @ ] => { $ crate :: SyntaxKind :: AT } ; [ # ] => { $ crate :: SyntaxKind :: POUND } ; [ ~ ] => { $ crate :: SyntaxKind :: TILDE } ; [ ? ] => { $ crate :: SyntaxKind :: QUESTION } ; [ $ ] => { $ crate :: SyntaxKind :: DOLLAR } ; [ & ] => { $ crate :: SyntaxKind :: AMP } ; [ | ] => { $ crate :: SyntaxKind :: PIPE } ; [ + ] => { $ crate :: SyntaxKind :: PLUS } ; [ * ] => { $ crate :: SyntaxKind :: STAR } ; [ / ] => { $ crate :: SyntaxKind :: SLASH } ; [ ^ ] => { $ crate :: SyntaxKind :: CARET } ; [ % ] => { $ crate :: SyntaxKind :: PERCENT } ; [ _ ] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [ . ] => { $ crate :: SyntaxKind :: DOT } ; [ .. ] => { $ crate :: SyntaxKind :: DOT2 } ; [ ... ] => { $ crate :: SyntaxKind :: DOT3 } ; [ ..= ] => { $ crate :: SyntaxKind :: DOT2EQ } ; [ : ] => { $ crate :: SyntaxKind :: COLON } ; [ :: ] => { $ crate :: SyntaxKind :: COLON2 } ; [ = ] => { $ crate :: SyntaxKind :: EQ } ; [ == ] => { $ crate :: SyntaxKind :: EQ2 } ; [ => ] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [ ! ] => { $ crate :: SyntaxKind :: BANG } ; [ != ] => { $ crate :: SyntaxKind :: NEQ } ; [ - ] => { $ crate :: SyntaxKind :: MINUS } ; [ -> ] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [ <= ] => { $ crate :: SyntaxKind :: LTEQ } ; [ >= ] => { $ crate :: SyntaxKind :: GTEQ } ; [ += ] => { $ crate :: SyntaxKind :: PLUSEQ } ; [ -= ] => { $ crate :: SyntaxKind :: MINUSEQ } ; [ |= ] => { $ crate :: SyntaxKind :: PIPEEQ } ; [ &= ] => { $ crate :: SyntaxKind :: AMPEQ } ; [ ^= ] => { $ crate :: SyntaxKind :: CARETEQ } ; [ /= ] => { $ crate :: SyntaxKind :: SLASHEQ } ; [ *= ] => { $ crate :: SyntaxKind :: STAREQ } ; [ %= ] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [ && ] => { $ crate :: SyntaxKind :: AMP2 } ; [ || ] => { $ crate :: SyntaxKind :: PIPE2 } ; [ << ] => { $ crate :: SyntaxKind :: SHL } ; [ >> ] => { $ crate :: SyntaxKind :: SHR } ; [ <<= ] => { $ crate :: SyntaxKind :: SHLEQ } ; [ >>= ] => { $ crate :: SyntaxKind :: SHREQ } ; [ as ] => { $ crate :: SyntaxKind :: AS_KW } ; [ async ] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [ await ] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [ box ] => { $ crate :: SyntaxKind :: BOX_KW } ; [ break ] => { $ crate :: SyntaxKind :: BREAK_KW } ; [ const ] => { $ crate :: SyntaxKind :: CONST_KW } ; [ continue ] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [ crate ] => { $ crate :: SyntaxKind :: CRATE_KW } ; [ dyn ] => { $ crate :: SyntaxKind :: DYN_KW } ; [ else ] => { $ crate :: SyntaxKind :: ELSE_KW } ; [ enum ] => { $ crate :: SyntaxKind :: ENUM_KW } ; [ extern ] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [ false ] => { $ crate :: SyntaxKind :: FALSE_KW } ; [ fn ] => { $ crate :: SyntaxKind :: FN_KW } ; [ for ] => { $ crate :: SyntaxKind :: FOR_KW } ; [ if ] => { $ crate :: SyntaxKind :: IF_KW } ; [ impl ] => { $ crate :: SyntaxKind :: IMPL_KW } ; [ in ] => { $ crate :: SyntaxKind :: IN_KW } ; [ let ] => { $ crate :: SyntaxKind :: LET_KW } ; [ loop ] => { $ crate :: SyntaxKind :: LOOP_KW } ; [ macro ] => { $ crate :: SyntaxKind :: MACRO_KW } ; [ match ] => { $ crate :: SyntaxKind :: MATCH_KW } ; [ mod ] => { $ crate :: SyntaxKind :: MOD_KW } ; [ move ] => { $ crate :: SyntaxKind :: MOVE_KW } ; [ mut ] => { $ crate :: SyntaxKind :: MUT_KW } ; [ pub ] => { $ crate :: SyntaxKind :: PUB_KW } ; [ ref ] => { $ crate :: SyntaxKind :: REF_KW } ; [ return ] => { $ crate :: SyntaxKind :: RETURN_KW } ; [ self ] => { $ crate :: SyntaxKind :: SELF_KW } ; [ static ] => { $ crate :: SyntaxKind :: STATIC_KW } ; [ struct ] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [ super ] => { $ crate :: SyntaxKind :: SUPER_KW } ; [ trait ] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [ true ] => { $ crate :: SyntaxKind :: TRUE_KW } ; [ try ] => { $ crate :: SyntaxKind :: TRY_KW } ; [ type ] => { $ crate :: SyntaxKind :: TYPE_KW } ; [ unsafe ] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [ use ] => { $ crate :: SyntaxKind :: USE_KW } ; [ where ] => { $ crate :: SyntaxKind :: WHERE_KW } ; [ while ] => { $ crate :: SyntaxKind :: WHILE_KW } ; [ auto ] => { $ crate :: SyntaxKind :: AUTO_KW } ; [ default ] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [ existential ] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [ union ] => { $ crate :: SyntaxKind :: UNION_KW } ; [ raw ] => { $ crate :: SyntaxKind :: RAW_KW } ; [ lifetime ] => { $ crate :: SyntaxKind :: LIFETIME } ; [ ident ] => { $ crate :: SyntaxKind :: IDENT } ; }
367 ( ; ) => {
368 $crate::SyntaxKind::SEMI
369 };
370 ( , ) => {
371 $crate::SyntaxKind::COMMA
372 };
373 ( '(' ) => {
374 $crate::SyntaxKind::L_PAREN
375 };
376 ( ')' ) => {
377 $crate::SyntaxKind::R_PAREN
378 };
379 ( '{' ) => {
380 $crate::SyntaxKind::L_CURLY
381 };
382 ( '}' ) => {
383 $crate::SyntaxKind::R_CURLY
384 };
385 ( '[' ) => {
386 $crate::SyntaxKind::L_BRACK
387 };
388 ( ']' ) => {
389 $crate::SyntaxKind::R_BRACK
390 };
391 ( < ) => {
392 $crate::SyntaxKind::L_ANGLE
393 };
394 ( > ) => {
395 $crate::SyntaxKind::R_ANGLE
396 };
397 ( @ ) => {
398 $crate::SyntaxKind::AT
399 };
400 ( # ) => {
401 $crate::SyntaxKind::POUND
402 };
403 ( ~ ) => {
404 $crate::SyntaxKind::TILDE
405 };
406 ( ? ) => {
407 $crate::SyntaxKind::QUESTION
408 };
409 ( $ ) => {
410 $crate::SyntaxKind::DOLLAR
411 };
412 ( & ) => {
413 $crate::SyntaxKind::AMP
414 };
415 ( | ) => {
416 $crate::SyntaxKind::PIPE
417 };
418 ( + ) => {
419 $crate::SyntaxKind::PLUS
420 };
421 ( * ) => {
422 $crate::SyntaxKind::STAR
423 };
424 ( / ) => {
425 $crate::SyntaxKind::SLASH
426 };
427 ( ^ ) => {
428 $crate::SyntaxKind::CARET
429 };
430 ( % ) => {
431 $crate::SyntaxKind::PERCENT
432 };
433 ( _ ) => {
434 $crate::SyntaxKind::UNDERSCORE
435 };
436 ( . ) => {
437 $crate::SyntaxKind::DOT
438 };
439 ( .. ) => {
440 $crate::SyntaxKind::DOTDOT
441 };
442 ( ... ) => {
443 $crate::SyntaxKind::DOTDOTDOT
444 };
445 ( ..= ) => {
446 $crate::SyntaxKind::DOTDOTEQ
447 };
448 ( : ) => {
449 $crate::SyntaxKind::COLON
450 };
451 ( :: ) => {
452 $crate::SyntaxKind::COLONCOLON
453 };
454 ( = ) => {
455 $crate::SyntaxKind::EQ
456 };
457 ( == ) => {
458 $crate::SyntaxKind::EQEQ
459 };
460 ( => ) => {
461 $crate::SyntaxKind::FAT_ARROW
462 };
463 ( ! ) => {
464 $crate::SyntaxKind::EXCL
465 };
466 ( != ) => {
467 $crate::SyntaxKind::NEQ
468 };
469 ( - ) => {
470 $crate::SyntaxKind::MINUS
471 };
472 ( -> ) => {
473 $crate::SyntaxKind::THIN_ARROW
474 };
475 ( <= ) => {
476 $crate::SyntaxKind::LTEQ
477 };
478 ( >= ) => {
479 $crate::SyntaxKind::GTEQ
480 };
481 ( += ) => {
482 $crate::SyntaxKind::PLUSEQ
483 };
484 ( -= ) => {
485 $crate::SyntaxKind::MINUSEQ
486 };
487 ( |= ) => {
488 $crate::SyntaxKind::PIPEEQ
489 };
490 ( &= ) => {
491 $crate::SyntaxKind::AMPEQ
492 };
493 ( ^= ) => {
494 $crate::SyntaxKind::CARETEQ
495 };
496 ( /= ) => {
497 $crate::SyntaxKind::SLASHEQ
498 };
499 ( *= ) => {
500 $crate::SyntaxKind::STAREQ
501 };
502 ( %= ) => {
503 $crate::SyntaxKind::PERCENTEQ
504 };
505 ( && ) => {
506 $crate::SyntaxKind::AMPAMP
507 };
508 ( || ) => {
509 $crate::SyntaxKind::PIPEPIPE
510 };
511 ( << ) => {
512 $crate::SyntaxKind::SHL
513 };
514 ( >> ) => {
515 $crate::SyntaxKind::SHR
516 };
517 ( <<= ) => {
518 $crate::SyntaxKind::SHLEQ
519 };
520 ( >>= ) => {
521 $crate::SyntaxKind::SHREQ
522 };
523 ( as ) => {
524 $crate::SyntaxKind::AS_KW
525 };
526 ( async ) => {
527 $crate::SyntaxKind::ASYNC_KW
528 };
529 ( await ) => {
530 $crate::SyntaxKind::AWAIT_KW
531 };
532 ( box ) => {
533 $crate::SyntaxKind::BOX_KW
534 };
535 ( break ) => {
536 $crate::SyntaxKind::BREAK_KW
537 };
538 ( const ) => {
539 $crate::SyntaxKind::CONST_KW
540 };
541 ( continue ) => {
542 $crate::SyntaxKind::CONTINUE_KW
543 };
544 ( crate ) => {
545 $crate::SyntaxKind::CRATE_KW
546 };
547 ( dyn ) => {
548 $crate::SyntaxKind::DYN_KW
549 };
550 ( else ) => {
551 $crate::SyntaxKind::ELSE_KW
552 };
553 ( enum ) => {
554 $crate::SyntaxKind::ENUM_KW
555 };
556 ( extern ) => {
557 $crate::SyntaxKind::EXTERN_KW
558 };
559 ( false ) => {
560 $crate::SyntaxKind::FALSE_KW
561 };
562 ( fn ) => {
563 $crate::SyntaxKind::FN_KW
564 };
565 ( for ) => {
566 $crate::SyntaxKind::FOR_KW
567 };
568 ( if ) => {
569 $crate::SyntaxKind::IF_KW
570 };
571 ( impl ) => {
572 $crate::SyntaxKind::IMPL_KW
573 };
574 ( in ) => {
575 $crate::SyntaxKind::IN_KW
576 };
577 ( let ) => {
578 $crate::SyntaxKind::LET_KW
579 };
580 ( loop ) => {
581 $crate::SyntaxKind::LOOP_KW
582 };
583 ( macro ) => {
584 $crate::SyntaxKind::MACRO_KW
585 };
586 ( match ) => {
587 $crate::SyntaxKind::MATCH_KW
588 };
589 ( mod ) => {
590 $crate::SyntaxKind::MOD_KW
591 };
592 ( move ) => {
593 $crate::SyntaxKind::MOVE_KW
594 };
595 ( mut ) => {
596 $crate::SyntaxKind::MUT_KW
597 };
598 ( pub ) => {
599 $crate::SyntaxKind::PUB_KW
600 };
601 ( ref ) => {
602 $crate::SyntaxKind::REF_KW
603 };
604 ( return ) => {
605 $crate::SyntaxKind::RETURN_KW
606 };
607 ( self ) => {
608 $crate::SyntaxKind::SELF_KW
609 };
610 ( static ) => {
611 $crate::SyntaxKind::STATIC_KW
612 };
613 ( struct ) => {
614 $crate::SyntaxKind::STRUCT_KW
615 };
616 ( super ) => {
617 $crate::SyntaxKind::SUPER_KW
618 };
619 ( trait ) => {
620 $crate::SyntaxKind::TRAIT_KW
621 };
622 ( true ) => {
623 $crate::SyntaxKind::TRUE_KW
624 };
625 ( try ) => {
626 $crate::SyntaxKind::TRY_KW
627 };
628 ( type ) => {
629 $crate::SyntaxKind::TYPE_KW
630 };
631 ( unsafe ) => {
632 $crate::SyntaxKind::UNSAFE_KW
633 };
634 ( use ) => {
635 $crate::SyntaxKind::USE_KW
636 };
637 ( where ) => {
638 $crate::SyntaxKind::WHERE_KW
639 };
640 ( while ) => {
641 $crate::SyntaxKind::WHILE_KW
642 };
643 ( auto ) => {
644 $crate::SyntaxKind::AUTO_KW
645 };
646 ( default ) => {
647 $crate::SyntaxKind::DEFAULT_KW
648 };
649 ( existential ) => {
650 $crate::SyntaxKind::EXISTENTIAL_KW
651 };
652 ( union ) => {
653 $crate::SyntaxKind::UNION_KW
654 };
655 ( raw ) => {
656 $crate::SyntaxKind::RAW_KW
657 };
658}
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs
index 00ea3a9b0..2d4f68f5e 100644
--- a/crates/ra_prof/src/lib.rs
+++ b/crates/ra_prof/src/lib.rs
@@ -113,21 +113,6 @@ pub fn profile(label: Label) -> Profiler {
113 }) 113 })
114} 114}
115 115
116pub fn print_time(label: Label) -> impl Drop {
117 struct Guard {
118 label: Label,
119 start: Instant,
120 }
121
122 impl Drop for Guard {
123 fn drop(&mut self) {
124 eprintln!("{}: {:?}", self.label, self.start.elapsed())
125 }
126 }
127
128 Guard { label, start: Instant::now() }
129}
130
131pub struct Profiler { 116pub struct Profiler {
132 label: Option<Label>, 117 label: Option<Label>,
133 detail: Option<String>, 118 detail: Option<String>,
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 15a8279f3..99c6b7219 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -42,11 +42,6 @@ pub trait AstNode {
42 fn syntax(&self) -> &SyntaxNode; 42 fn syntax(&self) -> &SyntaxNode;
43} 43}
44 44
45#[test]
46fn assert_ast_is_object_safe() {
47 fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
48}
49
50/// Like `AstNode`, but wraps tokens rather than interior nodes. 45/// Like `AstNode`, but wraps tokens rather than interior nodes.
51pub trait AstToken { 46pub trait AstToken {
52 fn can_cast(token: SyntaxKind) -> bool 47 fn can_cast(token: SyntaxKind) -> bool
@@ -64,22 +59,6 @@ pub trait AstToken {
64 } 59 }
65} 60}
66 61
67mod support {
68 use super::{AstChildren, AstNode, AstToken, SyntaxNode};
69
70 pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
71 parent.children().find_map(N::cast)
72 }
73
74 pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
75 AstChildren::new(parent)
76 }
77
78 pub(super) fn token<T: AstToken>(parent: &SyntaxNode) -> Option<T> {
79 parent.children_with_tokens().filter_map(|it| it.into_token()).find_map(T::cast)
80 }
81}
82
83/// An iterator over `SyntaxNode` children of a particular AST type. 62/// An iterator over `SyntaxNode` children of a particular AST type.
84#[derive(Debug, Clone)] 63#[derive(Debug, Clone)]
85pub struct AstChildren<N> { 64pub struct AstChildren<N> {
@@ -100,12 +79,25 @@ impl<N: AstNode> Iterator for AstChildren<N> {
100 } 79 }
101} 80}
102 81
103fn child_opt<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> Option<C> { 82mod support {
104 children(parent).next() 83 use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken};
84
85 pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
86 parent.children().find_map(N::cast)
87 }
88
89 pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
90 AstChildren::new(parent)
91 }
92
93 pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {
94 parent.children_with_tokens().filter_map(|it| it.into_token()).find(|it| it.kind() == kind)
95 }
105} 96}
106 97
107fn children<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> AstChildren<C> { 98#[test]
108 AstChildren::new(parent.syntax()) 99fn assert_ast_is_object_safe() {
100 fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
109} 101}
110 102
111#[test] 103#[test]
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs
index 069c6ee82..9e5411ee5 100644
--- a/crates/ra_syntax/src/ast/edit.rs
+++ b/crates/ra_syntax/src/ast/edit.rs
@@ -6,7 +6,7 @@ use std::{iter, ops::RangeInclusive};
6use arrayvec::ArrayVec; 6use arrayvec::ArrayVec;
7 7
8use crate::{ 8use crate::{
9 algo, 9 algo::{self, neighbor, SyntaxRewriter},
10 ast::{ 10 ast::{
11 self, 11 self,
12 make::{self, tokens}, 12 make::{self, tokens},
@@ -16,7 +16,6 @@ use crate::{
16 SyntaxKind::{ATTR, COMMENT, WHITESPACE}, 16 SyntaxKind::{ATTR, COMMENT, WHITESPACE},
17 SyntaxNode, SyntaxToken, T, 17 SyntaxNode, SyntaxToken, T,
18}; 18};
19use algo::{neighbor, SyntaxRewriter};
20 19
21impl ast::BinExpr { 20impl ast::BinExpr {
22 #[must_use] 21 #[must_use]
@@ -33,9 +32,9 @@ impl ast::FnDef {
33 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); 32 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
34 let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { 33 let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
35 old_body.syntax().clone().into() 34 old_body.syntax().clone().into()
36 } else if let Some(semi) = self.semi_token() { 35 } else if let Some(semi) = self.semicolon_token() {
37 to_insert.push(make::tokens::single_space().into()); 36 to_insert.push(make::tokens::single_space().into());
38 semi.syntax.clone().into() 37 semi.into()
39 } else { 38 } else {
40 to_insert.push(make::tokens::single_space().into()); 39 to_insert.push(make::tokens::single_space().into());
41 to_insert.push(body.syntax().clone().into()); 40 to_insert.push(body.syntax().clone().into());
@@ -99,7 +98,7 @@ impl ast::ItemList {
99 None => match self.l_curly_token() { 98 None => match self.l_curly_token() {
100 Some(it) => ( 99 Some(it) => (
101 " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(), 100 " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
102 InsertPosition::After(it.syntax().clone().into()), 101 InsertPosition::After(it.into()),
103 ), 102 ),
104 None => return self.clone(), 103 None => return self.clone(),
105 }, 104 },
@@ -143,7 +142,7 @@ impl ast::RecordFieldList {
143 macro_rules! after_l_curly { 142 macro_rules! after_l_curly {
144 () => {{ 143 () => {{
145 let anchor = match self.l_curly_token() { 144 let anchor = match self.l_curly_token() {
146 Some(it) => it.syntax().clone().into(), 145 Some(it) => it.into(),
147 None => return self.clone(), 146 None => return self.clone(),
148 }; 147 };
149 InsertPosition::After(anchor) 148 InsertPosition::After(anchor)
@@ -190,15 +189,15 @@ impl ast::RecordFieldList {
190impl ast::TypeParam { 189impl ast::TypeParam {
191 #[must_use] 190 #[must_use]
192 pub fn remove_bounds(&self) -> ast::TypeParam { 191 pub fn remove_bounds(&self) -> ast::TypeParam {
193 let colon = match self.colon() { 192 let colon = match self.colon_token() {
194 Some(it) => it, 193 Some(it) => it,
195 None => return self.clone(), 194 None => return self.clone(),
196 }; 195 };
197 let end = match self.type_bound_list() { 196 let end = match self.type_bound_list() {
198 Some(it) => it.syntax().clone().into(), 197 Some(it) => it.syntax().clone().into(),
199 None => colon.syntax().clone().into(), 198 None => colon.clone().into(),
200 }; 199 };
201 self.replace_children(colon.syntax().clone().into()..=end, iter::empty()) 200 self.replace_children(colon.into()..=end, iter::empty())
202 } 201 }
203} 202}
204 203
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 40c8fca3b..93aa3d45f 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -1,7 +1,7 @@
1//! Various extension methods to ast Expr Nodes, which are hard to code-generate. 1//! Various extension methods to ast Expr Nodes, which are hard to code-generate.
2 2
3use crate::{ 3use crate::{
4 ast::{self, child_opt, children, AstChildren, AstNode}, 4 ast::{self, support, AstChildren, AstNode},
5 SmolStr, 5 SmolStr,
6 SyntaxKind::*, 6 SyntaxKind::*,
7 SyntaxToken, T, 7 SyntaxToken, T,
@@ -36,7 +36,7 @@ impl ast::IfExpr {
36 let res = match self.blocks().nth(1) { 36 let res = match self.blocks().nth(1) {
37 Some(block) => ElseBranch::Block(block), 37 Some(block) => ElseBranch::Block(block),
38 None => { 38 None => {
39 let elif: ast::IfExpr = child_opt(self)?; 39 let elif: ast::IfExpr = support::child(self.syntax())?;
40 ElseBranch::IfExpr(elif) 40 ElseBranch::IfExpr(elif)
41 } 41 }
42 }; 42 };
@@ -44,17 +44,7 @@ impl ast::IfExpr {
44 } 44 }
45 45
46 fn blocks(&self) -> AstChildren<ast::BlockExpr> { 46 fn blocks(&self) -> AstChildren<ast::BlockExpr> {
47 children(self) 47 support::children(self.syntax())
48 }
49}
50
51impl ast::RefExpr {
52 pub fn is_mut(&self) -> bool {
53 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
54 }
55
56 pub fn raw_token(&self) -> Option<SyntaxToken> {
57 None // FIXME: implement &raw
58 } 48 }
59} 49}
60 50
@@ -212,15 +202,15 @@ impl ast::BinExpr {
212 } 202 }
213 203
214 pub fn lhs(&self) -> Option<ast::Expr> { 204 pub fn lhs(&self) -> Option<ast::Expr> {
215 children(self).next() 205 support::children(self.syntax()).next()
216 } 206 }
217 207
218 pub fn rhs(&self) -> Option<ast::Expr> { 208 pub fn rhs(&self) -> Option<ast::Expr> {
219 children(self).nth(1) 209 support::children(self.syntax()).nth(1)
220 } 210 }
221 211
222 pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) { 212 pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) {
223 let mut children = children(self); 213 let mut children = support::children(self.syntax());
224 let first = children.next(); 214 let first = children.next();
225 let second = children.next(); 215 let second = children.next();
226 (first, second) 216 (first, second)
@@ -275,10 +265,10 @@ impl ast::RangeExpr {
275 265
276impl ast::IndexExpr { 266impl ast::IndexExpr {
277 pub fn base(&self) -> Option<ast::Expr> { 267 pub fn base(&self) -> Option<ast::Expr> {
278 children(self).next() 268 support::children(self.syntax()).next()
279 } 269 }
280 pub fn index(&self) -> Option<ast::Expr> { 270 pub fn index(&self) -> Option<ast::Expr> {
281 children(self).nth(1) 271 support::children(self.syntax()).nth(1)
282 } 272 }
283} 273}
284 274
@@ -291,11 +281,11 @@ impl ast::ArrayExpr {
291 pub fn kind(&self) -> ArrayExprKind { 281 pub fn kind(&self) -> ArrayExprKind {
292 if self.is_repeat() { 282 if self.is_repeat() {
293 ArrayExprKind::Repeat { 283 ArrayExprKind::Repeat {
294 initializer: children(self).next(), 284 initializer: support::children(self.syntax()).next(),
295 repeat: children(self).nth(1), 285 repeat: support::children(self.syntax()).nth(1),
296 } 286 }
297 } else { 287 } else {
298 ArrayExprKind::ElementList(children(self)) 288 ArrayExprKind::ElementList(support::children(self.syntax()))
299 } 289 }
300 } 290 }
301 291
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index b50a89864..76b7655e6 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -5,9 +5,7 @@ use itertools::Itertools;
5use ra_parser::SyntaxKind; 5use ra_parser::SyntaxKind;
6 6
7use crate::{