Auto merge of #38099 - GuillaumeGomez:cast_suggestions, r=nikomatsakis · rust-lang/rust@439c312 (original) (raw)

`@@ -14,8 +14,13 @@ use rustc::ty::Ty;

`

14

14

`use rustc::infer::{InferOk};

`

15

15

`use rustc::traits::ObligationCause;

`

16

16

``

17

``

`-

use syntax_pos::Span;

`

``

17

`+

use syntax::ast;

`

``

18

`+

use syntax_pos::{self, Span};

`

18

19

`use rustc::hir;

`

``

20

`+

use rustc::hir::def::Def;

`

``

21

`+

use rustc::ty::{self, AssociatedItem};

`

``

22

+

``

23

`+

use super::method::probe;

`

19

24

``

20

25

`impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

`

21

26

`// Requires that the two types unify, and prints an error message if

`

`@@ -27,7 +32,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

`

27

32

`self.register_predicates(obligations);

`

28

33

`},

`

29

34

`Err(e) => {

`

30

``

`-

self.report_mismatched_types(&cause, expected, actual, e);

`

``

35

`+

self.report_mismatched_types(&cause, expected, actual, e).emit();

`

31

36

`}

`

32

37

`}

`

33

38

`}

`

`@@ -46,7 +51,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

`

46

51

`self.register_predicates(obligations);

`

47

52

`},

`

48

53

`Err(e) => {

`

49

``

`-

self.report_mismatched_types(cause, expected, actual, e);

`

``

54

`+

self.report_mismatched_types(cause, expected, actual, e).emit();

`

50

55

`}

`

51

56

`}

`

52

57

`}

`

`@@ -57,7 +62,65 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

`

57

62

`if let Err(e) = self.try_coerce(expr, checked_ty, expected) {

`

58

63

`let cause = self.misc(expr.span);

`

59

64

`let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);

`

60

``

`-

self.report_mismatched_types(&cause, expected, expr_ty, e);

`

``

65

`+

let mode = probe::Mode::MethodCall;

`

``

66

`+

let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,

`

``

67

`+

mode,

`

``

68

`+

expected,

`

``

69

`+

checked_ty,

`

``

70

`+

ast::DUMMY_NODE_ID);

`

``

71

`+

let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);

`

``

72

`+

if suggestions.len() > 0 {

`

``

73

`+

err.help(&format!("here are some functions which \

`

``

74

`+

might fulfill your needs:\n - {}",

`

``

75

`+

self.get_best_match(&suggestions)));

`

``

76

`+

};

`

``

77

`+

err.emit();

`

``

78

`+

}

`

``

79

`+

}

`

``

80

+

``

81

`+

fn format_method_suggestion(&self, method: &AssociatedItem) -> String {

`

``

82

`+

format!(".{}({})",

`

``

83

`+

method.name,

`

``

84

`+

if self.has_no_input_arg(method) {

`

``

85

`+

""

`

``

86

`+

} else {

`

``

87

`+

"..."

`

``

88

`+

})

`

``

89

`+

}

`

``

90

+

``

91

`+

fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> String {

`

``

92

`+

methods.iter()

`

``

93

`+

.take(5)

`

``

94

`+

.map(|method| self.format_method_suggestion(&*method))

`

``

95

`+

.collect::<Vec>()

`

``

96

`+

.join("\n - ")

`

``

97

`+

}

`

``

98

+

``

99

`+

fn get_best_match(&self, methods: &[AssociatedItem]) -> String {

`

``

100

`+

let no_argument_methods: Vec<_> =

`

``

101

`+

methods.iter()

`

``

102

`+

.filter(|ref x| self.has_no_input_arg(&*x))

`

``

103

`+

.map(|x| x.clone())

`

``

104

`+

.collect();

`

``

105

`+

if no_argument_methods.len() > 0 {

`

``

106

`+

self.display_suggested_methods(&no_argument_methods)

`

``

107

`+

} else {

`

``

108

`+

self.display_suggested_methods(&methods)

`

``

109

`+

}

`

``

110

`+

}

`

``

111

+

``

112

`` +

// This function checks if the method isn't static and takes other arguments than self.

``

``

113

`+

fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {

`

``

114

`+

match method.def() {

`

``

115

`+

Def::Method(def_id) => {

`

``

116

`+

match self.tcx.item_type(def_id).sty {

`

``

117

`+

ty::TypeVariants::TyFnDef(_, _, fty) => {

`

``

118

`+

fty.sig.skip_binder().inputs().len() == 1

`

``

119

`+

}

`

``

120

`+

_ => false,

`

``

121

`+

}

`

``

122

`+

}

`

``

123

`+

_ => false,

`

61

124

`}

`

62

125

`}

`

63

126

`}

`